我正在开发一个需要解析一些xml的iPhone项目。 xml可能包含也可能不包含默认命名空间。我需要知道如何解析xml以防它使用默认命名空间。因为我需要阅读一个写xml,我倾向于使用KissXML,但我愿意接受建议。
这是我的代码:
NSString *content = [NSString stringWithContentsOfFile:[[NSBundle mainBundle]
pathForResource:@"bookstore" ofType:@"xml"] encoding:NSUTF8StringEncoding error:nil];
DDXMLDocument *theDocument = [[DDXMLDocument alloc] initWithXMLString:content options:0 error:nil];
NSArray *results = [theDocument nodesForXPath:@"//book" error:nil];
NSLog(@"%d", [results count]);
它在xml:
上按预期工作<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
<book category="COOKING">
<title lang="en">Everyday Italian</title>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
</book>
</bookstore>
但是当xml有一个命名空间时,它会停止工作:
<?xml version="1.0" encoding="UTF-8"?>
<bookstore xmlns="[INSERT RANDOM NAMESPACE]">
<book category="COOKING">
<title lang="en">Everyday Italian</title>
</book>
<book category="CHILDREN">
<title lang="en">Harry Potter</title>
</book>
</bookstore>
当然,我可以预处理字符串并删除xmlns,虽然这感觉就像是一种丑陋的黑客。处理这个问题的正确方法是什么?
答案 0 :(得分:6)
您可以使用两个XPath查询,一个用于获取命名空间,然后注册它;作为第二个查询使用您已经拥有的名称空间。我只能帮助您查询,但似乎您对命名空间以及如何在KissXML框架中注册它们非常熟悉:
namespace-uri(/*)
此表达式从文档根开始提取所有子节点,每个XML定义是一个根元素,并返回它的命名空间uri。
似乎KissXML仅支持XPath 1.0。使用这种功能较弱的语言版本,您需要在每个轴步骤中使用通配符选择器,并在谓词中比较本地名称(不带名称空间前缀):
//*[local-name(.) = 'book']
从XPath 2.0开始,您可以使用名称空间通配符进行查询,该通配符要短得多:
//*:book
答案 1 :(得分:4)
根据this comment,KissXML实现“正确”行为,而NSXML则不行。哪个不完全有帮助。有proposed fix for this等待合并。
扩展已接受答案的第一个提议的解决方案,解决方法I found是重命名默认命名空间,然后在我的XPath查询中使用该前缀。类似的东西:
DDXMLNode *defaultNamespace = [document.rootElement namespaceForPrefix:@""];
defaultNamespace.name = @"default";
NSArray *xmlNodes = [[document rootElement] nodesForXPath:@"//default:foo/default:bar" error:nil];
这对我来说比文件的文本处理更清晰。您当然可以检查和处理命名空间冲突,但上述情况应该适用于大多数简单的情况。