xpath-显示多行节点文本的特定行(最后)

问题描述 投票:0回答:2

是否可以仅显示某些节点​​多行内容的特定行?我正在解析一些junit.xml,并且我想显示error节点的最后一行。因此,例如此数据:

<testsuite>
<testcase>
<error message="test setup failure">some
lines 
of a lenghty
stacktrace
    s.shutdown(socket.SHUT_RDWR)
E   OSError: [Errno 107] Transport endpoint is not connected</error>
</testcase>
<testcase>
<error message="test setup failure">some
lines 
of a lenghty
stacktrace
    raise Exception(&quot;Connection closed by remote!&quot;)
E   Exception: Connection closed by remote!</error>
</testcase>
</testsuite>

我只想显示

E   OSError: [Errno 107] Transport endpoint is not connected
E   Exception: Connection closed by remote!

通过以下任一方法获取全文都是微不足道的

/testsuite/testcase/error/text()
//error/text()

我尝试了以下xpath表达式:

//error/text()[last()]

但是他们没有工作。我可以像这样使用xmlstarlet实现我想要的:

xmlstarlet sel -t -m "//error" -v "substring-after(., 'E   ')" -n

但是我想知道是否可以通过纯XPath表达式实现类似的功能?

xml xpath xmlstarlet
2个回答
0
投票

尝试使用类似xpath的表达式

//testcase//error/substring-after(.,"E ")

输出应为:

OSError: [Errno 107] Transport endpoint is not connected
Exception: Connection closed by remote!

0
投票

由于xmlstarlet仅支持XPath 1.0,但不支持EXSLT扩展功能,所以我建议使用str:tokenize()对文本进行标记并返回最后一个标记。

EXSLT扩展功能在XPath中使用“ sel”命令(-m和-v)受支持,但是我无法使其正常工作。我认为这是因为xmlstarlet创建使用的内部XSLT的方式。

尽管通过创建自己的XSLT,我仍然可以使用“ tr”命令使它正常工作。

XSLT 1.0(test.xsl)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
  xmlns:exslt="http://exslt.org/common" 
  xmlns:str="http://exslt.org/strings" version="1.0" extension-element-prefixes="exslt str">
  <xsl:output omit-xml-declaration="yes" indent="no"/>

  <xsl:template match="/">
    <xsl:for-each select="//error">
      <xsl:if test="not(position()=1)">
        <xsl:text>&#xA;</xsl:text>
      </xsl:if>
      <xsl:value-of select="str:tokenize(.,'&#xA;')[last()]"/>
    </xsl:for-each>  
  </xsl:template>

</xsl:stylesheet>

xmlstarlet命令行

xmlstarlet tr test.xsl input.xml

输出

E   OSError: [Errno 107] Transport endpoint is not connected
E   Exception: Connection closed by remote!

如果您使用的是支持XSLT 2.0的产品,则可以执行以下操作:

for $err in //error return tokenize($err, '&#xA;')[last()]

示例]

© www.soinside.com 2019 - 2024. All rights reserved.