如何在单个 XPath 函数中连接每个元素的两个属性?
How can I concatenate two attributes per element in a single XPath function?
我有以下 XML:
<xml>
<entry key="e1" value="foo"/>
<entry key="e2" value="bar"/>
...
</xml>
我想从 XPath 获得以下输出:
e1: foo, e2: bar, ...
我尝试使用 string-join
但它没有用。任何想法哪个版本的 XPath 可以做到这一点?有可能吗?
(注意:我更喜欢 XPath 1.0 查询,但是,我认为这是不可能的)
I tried to use string-join but it didn't work. Any ideas on which XPath could do this? Is it even possible?
[...] I don't think it is possible)
为什么不可能?...
无论如何,正如评论中所暗示的那样,只需使用
concat(
entry[1]@key, ': ',
entry[1]@value, ', ',
entry[2]@key, ': ',
entry[2]@value)
其他方式:
- XPath 2.0:
string-join( (expr1, expr2, ...), '')
- XSLT 2.0:
<xsl:value-of select="expr1, expr2, ..." separator="" />
- XPath 3.0:
expr1 || expr2 || ...
使用字符串连接运算符
任何XSLT版本,为防止重复,使用模板匹配:
<xsl:template match="xml/entry">
<xsl:value-of select="@key" />
<xsl:text>: </xsl:text>
<xsl:value-of select="@value" />
<xsl:if test="position() != last()">,</xsl:if>
</xsl:template>
或更通用,在属性节点上应用模板并匹配如下:
<xsl:template match="@key | @value">
<xsl:value-of select="." />
<xsl:text>: </xsl:text>
</xsl:template>
<xsl:template match="@value">
<xsl:value-of select="@value" />
<xsl:text>, </xsl:text>
</xsl:template>
XSLT 3.0,使用文本值模板 (TVT) 编写模板:
<xsl:template match="xml/entry" expand-text="yes">{
@key}: {
@value,
if(position() != last()) then ',' else ()
}</xsl:template>
XPath 2.0,更通用的方法:
string-join(
for $i in xml/item
return concat($i/@key, ': ', $i/@value),
', ')
或更短:
string-join(xml/item/concat($i/@key, ': ', $i/@value, ', ')
... 或使用 higher-order functions (pdf) 在 XPath 3.0 中获得乐趣和更轻松(?)阅读:
let $combine = concat(?, ': ', ?)
return string-join(
for $i in xml/item
return $combine($i/@key, $i/@value),
', ')
甚至:
string-join(
for-each-pair(
xml/item/@key, (: combine this :)
xml/item/@value, (: with this :)
concat(?, ': ', ?)), (: using this, in order :)
', ') (: then join :)
注意:如果您不使用 XSLT,只需忽略模板方法,您可以坚持提到的功能。
如果不想使用优雅的string-join()
表达式:
string-join(/*/*/concat(@key, ': ', @value),
', ')
您仍然可以使用这个稍微长一点的表达式:
/*/*/concat(@key, ': ',
@value,
if(following-sibling::*[1])
then ', '
else ()
)
或者,您可以使用这个 XSLT 2.0 one-liner(当然它需要包含在适当的模板中,例如一个匹配 '/'
):
<xsl:value-of select="/*/*/concat(@key, ': ', @value)" separator="', '"/>
我有以下 XML:
<xml>
<entry key="e1" value="foo"/>
<entry key="e2" value="bar"/>
...
</xml>
我想从 XPath 获得以下输出:
e1: foo, e2: bar, ...
我尝试使用 string-join
但它没有用。任何想法哪个版本的 XPath 可以做到这一点?有可能吗?
(注意:我更喜欢 XPath 1.0 查询,但是,我认为这是不可能的)
I tried to use string-join but it didn't work. Any ideas on which XPath could do this? Is it even possible?
[...] I don't think it is possible)
为什么不可能?...
无论如何,正如评论中所暗示的那样,只需使用
concat(
entry[1]@key, ': ',
entry[1]@value, ', ',
entry[2]@key, ': ',
entry[2]@value)
其他方式:
- XPath 2.0:
string-join( (expr1, expr2, ...), '')
- XSLT 2.0:
<xsl:value-of select="expr1, expr2, ..." separator="" />
- XPath 3.0:
expr1 || expr2 || ...
使用字符串连接运算符 任何XSLT版本,为防止重复,使用模板匹配:
<xsl:template match="xml/entry"> <xsl:value-of select="@key" /> <xsl:text>: </xsl:text> <xsl:value-of select="@value" /> <xsl:if test="position() != last()">,</xsl:if> </xsl:template>
或更通用,在属性节点上应用模板并匹配如下:
<xsl:template match="@key | @value"> <xsl:value-of select="." /> <xsl:text>: </xsl:text> </xsl:template> <xsl:template match="@value"> <xsl:value-of select="@value" /> <xsl:text>, </xsl:text> </xsl:template>
XSLT 3.0,使用文本值模板 (TVT) 编写模板:
<xsl:template match="xml/entry" expand-text="yes">{ @key}: { @value, if(position() != last()) then ',' else () }</xsl:template>
XPath 2.0,更通用的方法:
string-join( for $i in xml/item return concat($i/@key, ': ', $i/@value), ', ')
或更短:
string-join(xml/item/concat($i/@key, ': ', $i/@value, ', ')
... 或使用 higher-order functions (pdf) 在 XPath 3.0 中获得乐趣和更轻松(?)阅读:
let $combine = concat(?, ': ', ?) return string-join( for $i in xml/item return $combine($i/@key, $i/@value), ', ')
甚至:
string-join( for-each-pair( xml/item/@key, (: combine this :) xml/item/@value, (: with this :) concat(?, ': ', ?)), (: using this, in order :) ', ') (: then join :)
注意:如果您不使用 XSLT,只需忽略模板方法,您可以坚持提到的功能。
如果不想使用优雅的string-join()
表达式:
string-join(/*/*/concat(@key, ': ', @value),
', ')
您仍然可以使用这个稍微长一点的表达式:
/*/*/concat(@key, ': ',
@value,
if(following-sibling::*[1])
then ', '
else ()
)
或者,您可以使用这个 XSLT 2.0 one-liner(当然它需要包含在适当的模板中,例如一个匹配 '/'
):
<xsl:value-of select="/*/*/concat(@key, ': ', @value)" separator="', '"/>