XSL xsl:evaluate 多个节点
XSL xsl:evaluate multiple nodes
如果 xPath 匹配多个节点,我如何确保 xsl:evaluate returns 一系列节点。
假设如下input.xml
<numlist key="K1">
<numlitm key="K2">C1</numlitm>
<numlitm key="K2">C2</numlitm>
<numlitm key="K3">C3</numlitm>
</numlist>
以及以下 XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xst="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="xs"
version="3.0">
<xsl:variable name="main-doc" select="/"/>
<xsl:template match="/">
<xsl:variable name="var">//*[@key='K2']</xsl:variable>
<xsl:variable name="eval">
<xsl:evaluate xpath="$var" context-item="$main-doc" />
</xsl:variable>
<xsl:copy-of select="$eval"/>
</xsl:template>
</xsl:stylesheet>
结果是
<numlitm key="K2">C1</numlitm>
<numlitm key="K2">C2</numlitm>
我希望存储在 eval
中的结果是两个元素的序列,这样我就可以通过 for-each 循环遍历两个 numlitm
(我需要这个构造密钥)。问题是结果似乎不是节点序列,因此 for-each 迭代将产生两个 numlitm 行,而不是单独迭代中的每一行
The issue is that the result seems not to be a node sequence, thus a for-each iteration will yield both numlitm rows, instead of each row in one seperate iteration
你的假设是错误的。它可能是基于 xsl:for-each
指令的错误实现 - 您的问题忽略了这一点。如果你这样做:
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="main-doc" select="/"/>
<xsl:template match="/">
<xsl:variable name="var">//*[@key='K2']</xsl:variable>
<xsl:variable name="eval">
<xsl:evaluate xpath="$var" context-item="$main-doc" />
</xsl:variable>
<output>
<xsl:for-each select="$eval/numlitm">
<item>
<xsl:value-of select="." />
</item>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
您将获得以下预期结果:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<item>C1</item>
<item>C2</item>
</output>
变量的默认类型是文档节点。因此,将您的变量键入 element()
的序列,或者至少是 item()
.
的序列
<xsl:variable name="eval" as="element()*">
或
<xsl:variable name="eval" as="item()*">
然后 $eval
将是从评估的 XPath 中选择的项目的序列。
如果我没理解错的话,您想要同一个密钥的串行字符串。
→ 你可以尝试这样的事情:
<root>
<xsl:for-each-group select="//numlitm" group-by="@key">
<xsl:variable name="currentKey" select="@key"/>
<SameKey>
<!-- Serialize Nodestrings -->
<xsl:variable name="nodestrings">
<xsl:apply-templates select="//numlitm[@key=$currentKey]/text()" mode="serialize"/> <!-- get all tag-values for current group-key -->
</xsl:variable>
<key><xsl:value-of select="$currentKey"/></key>
<keyValues><xsl:value-of select="$nodestrings"/></keyValues>
</SameKey>
</xsl:for-each-group>
</root>
为此,您将收到以下输出:
<root>
<SameKey>
<key>K2</key>
<keyValues>C1C2</keyValues>
</SameKey>
<SameKey>
<key>K3</key>
<keyValues>C3</keyValues>
</SameKey>
</root>
如果 xPath 匹配多个节点,我如何确保 xsl:evaluate returns 一系列节点。
假设如下input.xml
<numlist key="K1">
<numlitm key="K2">C1</numlitm>
<numlitm key="K2">C2</numlitm>
<numlitm key="K3">C3</numlitm>
</numlist>
以及以下 XSL
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xst="http://www.w3.org/1999/XSL/Transform"
exclude-result-prefixes="xs"
version="3.0">
<xsl:variable name="main-doc" select="/"/>
<xsl:template match="/">
<xsl:variable name="var">//*[@key='K2']</xsl:variable>
<xsl:variable name="eval">
<xsl:evaluate xpath="$var" context-item="$main-doc" />
</xsl:variable>
<xsl:copy-of select="$eval"/>
</xsl:template>
</xsl:stylesheet>
结果是
<numlitm key="K2">C1</numlitm>
<numlitm key="K2">C2</numlitm>
我希望存储在 eval
中的结果是两个元素的序列,这样我就可以通过 for-each 循环遍历两个 numlitm
(我需要这个构造密钥)。问题是结果似乎不是节点序列,因此 for-each 迭代将产生两个 numlitm 行,而不是单独迭代中的每一行
The issue is that the result seems not to be a node sequence, thus a for-each iteration will yield both numlitm rows, instead of each row in one seperate iteration
你的假设是错误的。它可能是基于 xsl:for-each
指令的错误实现 - 您的问题忽略了这一点。如果你这样做:
<xsl:stylesheet version="3.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="main-doc" select="/"/>
<xsl:template match="/">
<xsl:variable name="var">//*[@key='K2']</xsl:variable>
<xsl:variable name="eval">
<xsl:evaluate xpath="$var" context-item="$main-doc" />
</xsl:variable>
<output>
<xsl:for-each select="$eval/numlitm">
<item>
<xsl:value-of select="." />
</item>
</xsl:for-each>
</output>
</xsl:template>
</xsl:stylesheet>
您将获得以下预期结果:
<?xml version="1.0" encoding="UTF-8"?>
<output>
<item>C1</item>
<item>C2</item>
</output>
变量的默认类型是文档节点。因此,将您的变量键入 element()
的序列,或者至少是 item()
.
<xsl:variable name="eval" as="element()*">
或
<xsl:variable name="eval" as="item()*">
然后 $eval
将是从评估的 XPath 中选择的项目的序列。
如果我没理解错的话,您想要同一个密钥的串行字符串。 → 你可以尝试这样的事情:
<root>
<xsl:for-each-group select="//numlitm" group-by="@key">
<xsl:variable name="currentKey" select="@key"/>
<SameKey>
<!-- Serialize Nodestrings -->
<xsl:variable name="nodestrings">
<xsl:apply-templates select="//numlitm[@key=$currentKey]/text()" mode="serialize"/> <!-- get all tag-values for current group-key -->
</xsl:variable>
<key><xsl:value-of select="$currentKey"/></key>
<keyValues><xsl:value-of select="$nodestrings"/></keyValues>
</SameKey>
</xsl:for-each-group>
</root>
为此,您将收到以下输出:
<root>
<SameKey>
<key>K2</key>
<keyValues>C1C2</keyValues>
</SameKey>
<SameKey>
<key>K3</key>
<keyValues>C3</keyValues>
</SameKey>
</root>