2013-06-26 158 views
3

我正在研究需要解析某些xml的iPhone项目。 xml可能包含或不包含默认名称空间。我需要知道如何解析xml以防使用默认名称空间。由于我需要同时阅读一个写xml,我倾向于使用KissXML,但我愿意提供建议。(吻)XML xpath和默认名称空间

这是我的代码:

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,尽管这感觉像是一种丑陋的黑客。处理这个问题的正确方法是什么?

回答

6

的清洁方式:查询的命名空间

您可以使用两种XPath查询,一个获取的命名空间,然后将其注册;作为第二个查询使用你已有的名称空间。我只能帮你查询,但似乎你很熟悉的命名空间以及如何将它们在KissXML框架注册:

namespace-uri(/*) 

这个表达式获取所有子节点开始在文档根目录,这是每个XML定义一个根元素,并返回它的名称空间uri。

的丑陋的方式:只有通过测试的本地名称

看来KissXML仅支持XPath 1.0。有了这个能力较少的语言版本,则需要在每个轴步骤中使用通配符选择和比较本地名称(不带命名空间前缀)的谓词中:

//*[local-name(.) = 'book'] 

从XPath 2.0中开始,您可以查询使用命名空间通配符,这更短:

//*:book 
+0

无数小时的谷歌搜索,研究,拉毛......我无法感谢你。 – caoimghgin

4

根据this comment而NSXML不KissXML实现“正确”的行为。这并不完全有帮助。有一个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]; 

这对我来说似乎比对文件的文本处理更清洁。你当然可以检查和处理命名空间冲突,但上述应该在大多数简单情况下工作。

相关问题