在Cocoa中读取、修改、写入XML文件

9
我正在寻找一个有关如何使用Cocoa读取、修改一个值并写入XML文件的简短示例/教程。我找到的所有内容要么太简单(只是读取或写入),要么太复杂(成为完整的XML编辑器)。
这似乎是一个非常标准的使用场景,所以我希望能找到一些相关资料...

可能是[Cocoa/Obj-C简单的XML文件阅读器-需要帮助]的重复问题(http://stackoverflow.com/questions/5274513/cocoa-obj-c-simple-xml-file-reader-need-help)。 - jscs
1
谢谢,但我正在寻找一个示例,展示如何读取、修改 并且 写入xml树。 'duplicates'不会这样做。假设我在xml文件中有一个简单的计数器:<counter>1</counter>。我该如何解析、增加并将其写回文件? - hanno
3个回答

6
我之前的说法是错误的,我声称无法编写这些元素。 苹果有两个XML解析器,一个用于NSDictionary/NSArray/NSString/NSNumber等对象,另一个称为NSXMLDocument。
我已经删除了之前的代码,该代码适用于Mac OS X 10.3;下面提到的代码将允许您拥有包含任何想要的标签和属性的xml文件。 在我的示例中,该代码将创建一个XML文件,类似于以下内容: 1 注意:如果想进一步减少代码,甚至可以移除“counter”,并将“root”重命名为“counter”。
新代码兼容Mac OS X 10.4及以上版本,已经过测试,并且可以直接使用。
- (void)incrementCounter
{
    NSXMLDocument   *xmlDoc;
    NSError         *error;
    NSURL           *url;
    NSXMLElement    *root;
    id              item;
    NSData          *data;
    NSArray         *children;
    int             counter;
    NSString        *pathname;

    pathname = [@"~/myFile" stringByExpandingTildeInPath];
    url = [NSURL fileURLWithPath:pathname];

    xmlDoc = [[NSXMLDocument alloc] initWithContentsOfURL:url options:NSXMLDocumentTidyXML error:&error];
    if(xmlDoc)
    {
        root = [xmlDoc rootElement];
    }
    else
    {
        root = [NSXMLNode elementWithName:@"root"];
        xmlDoc = [[NSXMLDocument alloc] initWithRootElement:root];
    }

    // fetch value:
    children = [root nodesForXPath:@"counter" error:&error];
    item = [children count] ? [children objectAtIndex:0] : NULL;

    // modify value:
    counter = item ? [[item stringValue] intValue] : 0;
    counter++;
    if(NULL == item)
    {
        item = [NSXMLNode elementWithName:@"counter" stringValue:@"0"];
        [root insertChild:item atIndex:0];
    }
    [item setStringValue:[[NSNumber numberWithInt:counter] stringValue]];

    // write:
    data = [xmlDoc XMLData];
    [data writeToURL:url atomically:YES];
}

这个答案对我来说毫无意义。 - hanno
我已经重新撰写了我的答案。如果您需要支持低于10.4的Mac OS X,我将不得不再次重写我的答案。这完全取决于您是否有NSXMLDocument类可用。 - user1985657
你用上面的新代码让它工作了吗?还是仍然有问题?尝试在一个全新的项目中从-awakeFromNib调用[self incrementCounter];,它应该会在你的主目录中生成“myFile”并在每次运行程序时递增计数器。 - user1985657

2

这是我对问题的解决方案 - 只有我将之前读取和解析的文件写出的部分...

使用PacMan的解决方案时,我遇到了一个问题,即输出的XML文件没有很好地格式化没有换行符)。

另一点是,我通常更喜欢使用XPath在XML文档中进行导航。

我的代码是类的一部分,因此我对每个节点都有一个属性(NSString* cfaLayout和NSInteger bitsPerPixel):

-(BOOL) savePropertiesFile{
BOOL isSuccess=FALSE;
NSError* error;
NSXMLElement* currentElement;
NSArray* nodes;

/* parse existing url file before saving it to new url */
if([_documentUrl checkResourceIsReachableAndReturnError:&error]==YES){
    self.document=[[NSXMLDocument alloc]
                                 initWithContentsOfURL:_documentUrl
                                 options:0
                                 error:&error];

    /* check top node */
    nodes=[_document nodesForXPath:@"/ImageFormat-Properties"
                                                     error:&error];
    if([nodes count]==0){
        return FALSE;
    }

    /* cfa layout */
    nodes=[_document nodesForXPath:@"/ImageFormat-Properties/ImageFormatDetails/CFALayout[text()]"
                                                     error:&error];
    if([nodes count]>0){
        currentElement=[nodes objectAtIndex:0];
        [currentElement setStringValue:[_cfaLayout lowercaseString]];
    }
    else{
        return FALSE;
    }

    /* bitsPerPixel */
    nodes=[_document nodesForXPath:@"/ImageFormat-Properties/ImageFormatDetails/BitsPerPixel[text()]"
                                                     error:&error];
    if([nodes count]>0){
        currentElement=[nodes objectAtIndex:0];
        [currentElement setStringValue:[NSString stringWithFormat: @"%ld", (long)_bitsPerPixel]];
    }
    else{
        return FALSE;
    }
}
[_document setDocumentContentKind:NSXMLDocumentXMLKind];
[_document setCharacterEncoding:@"UTF-8"];
[_document validateAndReturnError:&error];
if(error){
    return FALSE;
}

[self setDocumentUrl:_documentSaveAsUrl];
NSData* xmlData=[_document XMLDataWithOptions:NSXMLNodePrettyPrint];
isSuccess=[xmlData writeToURL:_documentSaveAsUrl atomically:YES];

return isSuccess;

}

或许对某些人有用...


输出的XML文件格式不好(没有任何换行):尝试使用“NSData *data = [xmlDoc XMLDataWithOptions:NSXMLNodePrettyPrint];” - geowar

-4

如果您不熟悉xpath,我建议您先了解一下。xpath是在XML树中查找节点的一种方法。


6
这不是回答,孩子。他正在问一个具体的问题,建议他“读一下”xpaths只会显得粗鲁。我同意楼主的看法。就我个人而言,我可以找到无数种在Cocoa中读取XML的方法,但是我却找不到一种明显的方法将NSArray、NSDictionary等转换为XML“对象”! - Alex Gray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接