根据XmlStarlet中的动态表达式返回值

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

我想根据“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 中使用 
xmlstarlet
1个回答
0
投票
时要记住的一点是,它用于创建 XSLT 来执行查询。这意味着我们可以使用

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="'&#10;'"/>
    </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()&gt;1]">
      <xsl:value-of select="'&#10;'"/>
      <xsl:value-of select="."/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

不幸的是,没有办法使用
xsl:key
这将是执行此查询的最有效方法。不过,您可以使用

xsl:key

 编写 XSLT 并使用 xmlstarlet 执行它。虽然效率更高,但有点复杂,而您正在寻找“更简单”。

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