2011-05-14 59 views
6

这是我的XML的一部分:使用XPath和VTD-XML获得子节点和元素的文本字符串

<MAIN> 
    <L> 
     <D>string1 string2 <b>string3</b> string4</D> 
    </L> 
    <L> 
     <D>string5 string6 <b>string7</b> string8 <i>string9</i></D> 
    </L> 
</MAIN> 

I want to get the content of all the <D> tags as string. So, the example above should return: 

1st iteration: 'string1 string2 <b>string3</b> string4' 
2nd iteration: 'string5 string6 <b>string7</b> string8 <i>string9</i>' 
etc... 

在VTD-XML的我用了一个自动驾驶仪的XPath“//大号/ D“和”// L/D/text()“,但没有奏效。

任何意见或替代方法将不胜感激。

问候

+0

难道你不能只使用// L将返回一个节点列表。然后,对于那些节点循环直接的孩子,并调用任何方法返回文本。 – gshauger 2011-05-14 20:15:22

+0

好问题,+1。查看我的答案,获取完整而简短的XPath表达式解决方案。 – 2011-05-15 16:46:50

回答

12

下面是已经做了你在找什么的代码。

VTDGen vg = new VTDGen(); 
    if (vg.parseFile("c://xml//alex.txt", true)){ 
     VTDNav vn = vg.getNav(); 
     AutoPilot ap = new AutoPilot(vn); 
     ap.selectXPath("//L/D"); 
     int i=-1; 
     while((i=ap.evalXPath())!=-1){ 
      long l = vn.getContentFragment(); 
      System.out.println(" -==> "+ vn.toString((int)l, (int)(l>>32))); 
     } 
    } 
+0

非常感谢!这解决了我的问题。 – Alex 2011-05-17 21:44:30

+0

@alex,你好! – 2011-05-20 09:43:24

+0

我开始使用这种方法,但它似乎破坏逃逸的字符。例如,如果内容有'&',打印的字符串只有“&”。我遇到了这个问题,并将其作为单独的问题发布[这里](http://stackoverflow.com/questions/27823107/vtd-xml-seems-to-be-spoiling-escaped-string-in-xml -文件)。 – 2015-01-07 16:07:21

3

使用

/*/L/D/node() 

这里选择任何D元素是一个孩子的孩子的所有节点(元素,文本节点,处理的指令和注释节点)任何L元素是XML文档顶部元素的子元素。

或者,你可以分别选择两个/*/L/D元素的所有节点的孩子:

/*/L[1]/D/node() 

/*/L[2]/D/node() 

验证使用XSLT作为XPath的的主机:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:copy-of select="/*/L[1]/D/node()"/> 
-------------------- 
    <xsl:copy-of select="/*/L[2]/D/node()"/> 
</xsl:template> 
</xsl:stylesheet> 

时所提供的XML文档应用:

<MAIN> 
    <L> 
     <D>string1 string2 
      <b>string3</b> string4 
     </D> 
    </L> 
    <L> 
     <D>string5 string6 
      <b>string7</b> string8 
      <i>string9</i> 
     </D> 
    </L> 
</MAIN> 

想要的,正确的结果产生

string1 string2 
      <b>string3</b> string4 

-------------------- 
    string5 string6 
      <b>string7</b> string8 
      <i>string9</i> 
+0

感谢您的回复。这没有奏效。它遍历D标签内的节点,因此在第一个D标签上它会转到b标签,在第二个D标签上它首先转到b标签,然后转到i标签。 – Alex 2011-05-15 17:41:57

+0

@Alex:如果是这种情况,那么您没有使用符合XPath的实现 - 节点测试node()必须选择当前节点的所有子节点 - 不仅是元素。我怀疑当正确的操作是检查所有选定的节点时,您只检查生成的节点列表中的元素。 – 2011-05-15 17:49:31

+0

@alex,是否是vtd-xml的错误? – 2011-05-16 02:10:35