我想根据“part1”中给出的值获取文本元素。
在下面的示例 XML 中,我希望返回
Text2
和 Text5
,因为 part1
中的值引用 2
和 5
。
如何使用 XmlStarlet 来完成此操作,最好在 Windows 下。
我开始于:
xml sel -t -m //part1/line -v @val -o "," -c ../../part2/line[@val='3']/text -n example.xml
给予:
2,<text>Text 3</text>
5,<text>Text 3</text>
这当然不正确,因为我确实想要固定的
3
,但这应该是动态的,例如:
xml sel -t -m //part1/line -v @val -o "," -c concat('../../part2/line[@val=',@val,']/text') -n example.xml
返回 Xml 路径,而不是我期望的值:
2,../../part2/line[@val=2]/text
5,../../part2/line[@val=5]/text
我期待返回下一条短信。
2,<text>Text 2</text>
5,<text>Text 5</text>
(这里真的不需要
<text>
和</text>
...)
可以使用 XmlStarlet 来完成(最好在 Windows 下)吗?
example.xml 是:
<root>
<part1>
<line val="2"></line>
<line val="5"></line>
</part1>
<part2>
<line val="1">
<text>Text 1</text>
</line>
<line val="2">
<text>Text 2</text>
</line>
<line val="3">
<text>Text 3</text>
</line>
<line val="4">
<text>Text 4</text>
</line>
<line val="5">
<text>Text 5</text>
</line>
<line val="6">
<text>Text 6</text>
</line>
</part2>
</root>
编辑:一如既往,在发布问题后得到一个想法
我希望有一个比(产生正确结果!)更简单的解决方案:
for /f "usebackq tokens=*" %f in (`xml sel -t -m //part1/line -v @val -n example.xml`) do @xml sel -t -m //part2/line[@val=%f]/text -v "%f" -o "," -v . -n example.xml
在 xmlstarlet 中使用
current()
。尝试:
xml sel -t -m "//part1/line/@val" -v "concat(.,',',//part2/line[current()=@val]/text)" -n example.xml
它产生:
2,Text 2
5,Text 5
如果我们将
-C
添加到命令行,我们可以看到生成的 XSLT...
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:exslt="http://exslt.org/common" version="1.0" extension-element-prefixes="exslt">
<xsl:output omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/">
<xsl:for-each select="//part1/line/@val">
<xsl:call-template name="value-of-template">
<xsl:with-param name="select" select="concat(.,',',//part2/line[current()=@val]/text)"/>
</xsl:call-template>
<xsl:value-of select="' '"/>
</xsl:for-each>
</xsl:template>
<xsl:template name="value-of-template">
<xsl:param name="select"/>
<xsl:value-of select="$select"/>
<xsl:for-each select="exslt:node-set($select)[position()>1]">
<xsl:value-of select="' '"/>
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
不幸的是,没有办法使用 xsl:key
这将是执行此查询的最有效方法。不过,您可以使用 xsl:key
编写 XSLT 并使用 xmlstarlet 执行它。虽然效率更高,但有点复杂,而您正在寻找“更简单”。