KissXML的XPath选取问题

XMPPFramework用的XML解析库还是大神自己写的KissXML,有些人生下来就是让人仰望的,哎。

进入主题,如下一段XML:

  1. <paramsxmlns="namespace">
  2. <paramname="text">text in element</param>
  3. <paramname="voice">voice in element</param>
  4. </params>

需要得到各个<param/>子元素中的键值对应关系text->text in elementvoice->voice in element。最简单的方法就是用XPath选取指定的元素。

KissXML的NSXMLElement类的父类NSXMLNode有一个通过XPath选取子元素得到数组的方法:

  1. -(NSArray*)nodesForXPath:(NSString*)xpath error:(NSError**)error;

试之,竟然返回为空。。搜之,发现KissXML上已经有人开了issue,还有热心人把代码都补上了,这个世界上还是好人多啊。

前面的方法不能是因为<params/>中设置了namespace,需要为元素注册这个namespace,所以修改后的方法为:

  1. -(NSArray*)nodesForXPath:(NSString*)xpath namespaceMappings:(NSDictionary*)namespaceMappings error:(NSError**)error

第一步: 在namespaceMappings中设置一个命名空间的别名,如这样的:@{@"prefix":@"namespace"} ;

第二步: 在XPath中使用别名 //prefix:param

  1. NSString*xmlstring =@"<params xmlns=\"namespace\" >"
  2. @"<param name=\"text\">text in element</param>"
  3. @"<param name=\"voice\">voice in element</param>"
  4. @"</params>";
  5. NSXMLElement*element =[[NSXMLElement alloc] initWithXMLString:xmlstring error:nil];
  6. NSDictionary*namespaceMap=@{@"prefix":@"namespace"};
  7. NSArray*subelements =[element nodesForXPath:@"//prefix:param" namespaceMappings:namespaceMap error:nil];
  8. for(NSXMLElement*e in subelements){
  9. NSLog(@"sublelement: %@",[e XMLString]);
  10. }

这样就可以选到<param/>子元素了。

  1. 2013-08-0117:35:04.624ChatModule[14387:c07] sublelement:<param name="text">text in element</param>
  2. 2013-08-01 17:35:04.625 ChatModule[14387:c07] sublelement: <param name="voice">voice in element</param>

进一步的,如果想要选择nametext<param/>元素,可以使用更精确的XPath: //prefix:param[@name='text']

关于为什么要注册namespace,还需要读libxml2的代码,后面抽时间看一下,改动后的代码中加了这么一段:

  1. if(namespaceMappings){
  2. for(NSString* k in namespaceMappings){
  3. NSString* v =[namespaceMappings objectForKey:k];
  4. xmlXPathRegisterNs(xpathCtx,[k xmlChar],[v xmlChar]);
  5. }
  6. }

看SO上有人直接用libxml2的时候也有这个问题,xpath-query-for-a-node

关于XPath的语法,戳这里 .

完。

posted @ 2013-11-29 15:25  菁菁工作室  阅读(841)  评论(0编辑  收藏  举报