xpath - 如果xml文档仅放在一行上,则节点测试文本()不起作用

时间:2013-11-26 13:21:34

标签: xml xpath

我在放在一行上的xml文档上使用xpath text()函数时遇到了麻烦。如果在完全相同的xml版本的漂亮打印版本上使用,text()工作正常。

在这种情况下,我使用ruby和nokogiri,但我在firefox附加组件XPath Checker中看到了相同的行为。我对nokogiri和XPath Checker都得到了完全相同的结果。

顺便说一下:

工作:

doc = Nokogiri::XML::Document.parse <<-EOXML
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <ns:getOSVersionResponse xmlns:ns="http://www.cisco.com/AXL/API/8.5">
      <return>
        <os>
          <osName>Linux</osName>
          <osVersion>2.6.18-194.26.1.el5PAE</osVersion>
          <aarNeighborhoodName/>
        </os>
      </return>
    </ns:getOSVersionResponse>
  </soapenv:Body>
</soapenv:Envelope>
EOXML

不工作:

doc = Nokogiri::XML::Document.parse <<-EOXML
<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><ns:getOSVersionResponse xmlns:ns="http://www.cisco.com/AXL/API/8.5"><return><os><osName>Linux</osName><osVersion>2.6.18-194.26.1.el5PAE</osVersion><aarNeighborhoodName/></os></return></ns:getOSVersionResponse></soapenv:Body></soapenv:Envelope>
EOXML

Xpath查询:

doc.xpath("//*[not(text())]")

我的最终目标是找到并删除空的xml节点(在这种情况下为<aarNeighborhoodName/>)。

使用漂亮的xml我找到一个空标签(这是正确的):

> doc.xpath("//*[not(text())]")
=> [#<Nokogiri::XML::Element:0x1862238 name="aarNeighborhoodName">]
> doc.xpath("//*[not(text())]").length
=> 1

将xml放在一行上我有

> doc.xpath("//*[not(text())]").length
=> 6

这是错误的,因为我没有六个空的xml节点。

如何使用单行xml文档使xpath工作?

谢谢

1 个答案:

答案 0 :(得分:1)

//*[not(text())]将为您提供所有没有任何直接子节点的文本节点元素。当您的XML全部在一行上时,除osNameosVersion之外的所有元素都是如此,因为它们没有任何子文本节点,只有子元素。当XML被漂亮打印时,大多数元素都有文本节点子节点,它们完全由空格组成,这就是为什么它在这种情况下似乎“有效”。

如果要测试完全为空的元素,根本没有子节点(文本节点,元素,注释......),请使用

//*[not(node())]

请注意,属性节点在XPath数据模型中不被视为“子”,因此仍会选择<emptyElement with="attribute" />之类的内容。如果你想要排除那些,那么你需要

//*[not(@*|node())]