xpath - 显示多行节点文本的特定行(最后一行)
xpath - show specific line (last) of a multiline node text
是否可以只显示某些节点多行内容的特定行?我正在解析一些 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("Connection closed by remote!")
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 表达式实现类似的东西?
尝试使用像
这样的 xpath 表达式
//testcase//error/substring-after(.,"E ")
输出应该是:
OSError: [Errno 107] Transport endpoint is not connected
Exception: Connection closed by remote!
由于 xmlstarlet 仅支持 XPath 1.0,但支持 EXSLT 扩展函数,因此我建议使用 str:tokenize() 对文本进行标记,return 最后一个标记。
XPath 使用 "sel" 命令(-m 和 -v)支持 EXSLT 扩展函数,但我无法让它工作。我认为这是因为 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>
</xsl:text>
</xsl:if>
<xsl:value-of select="str:tokenize(.,'
')[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, '
')[last()]
注意:在某些在线 XPath 测试程序中,您可能需要将 

更改为 \n
。
是否可以只显示某些节点多行内容的特定行?我正在解析一些 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("Connection closed by remote!")
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 表达式实现类似的东西?
尝试使用像
这样的 xpath 表达式//testcase//error/substring-after(.,"E ")
输出应该是:
OSError: [Errno 107] Transport endpoint is not connected
Exception: Connection closed by remote!
由于 xmlstarlet 仅支持 XPath 1.0,但支持 EXSLT 扩展函数,因此我建议使用 str:tokenize() 对文本进行标记,return 最后一个标记。
XPath 使用 "sel" 命令(-m 和 -v)支持 EXSLT 扩展函数,但我无法让它工作。我认为这是因为 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>
</xsl:text>
</xsl:if>
<xsl:value-of select="str:tokenize(.,'
')[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, '
')[last()]
注意:在某些在线 XPath 测试程序中,您可能需要将 

更改为 \n
。