XSLT-2.0:将来自 current-group() 的结果合并为一个
XSLT-2.0: Combining results from current-group() into one
使用 SaxonHE 9.7/XPath-2.0
我的XML:
<osm>
<node>
<tag k="fhrs:id" v="204258"/>
<tag k="name" v="King of Wessex"/>
</node>
<node>
<tag k="fhrs:id" v="139245"/>
<tag k="name" v="The Royal Oak"/>
</node>
<node>
<tag k="fhrs:id" v="204258"/>
<tag k="name" v="The Rising Sun"/>
</node>
etc...
</osm>
我正在返回 fhrs:id
的所有重复值 (v=
) 使用:
<xsl:template match="/">
<xsl:for-each-group select="/*/*/tag[@k='fhrs:id']" group-by="@v">
<xsl:apply-templates select="current-group() [current-group()[2]]"/>
</xsl:for-each-group>
</xsl:template>
我正在将输出转换为 geojson 格式。这要求除最后一个元素之外的每个元素都以逗号结尾。在其他例程中,我用它来测试它是否是最后一个:
<xsl:template match="/*/*/tag">
{
...<snip>...
}<xsl:if test="position() < last()">,</xsl:if>
</xsl:template>
但是,因为在这种情况下 xsl:apply-templates
一次只传递两个,所以 geojson 输出中的每个其他元素都缺少一个逗号。
有没有一种方法可以将 xsl:for-each-group
的所有输出合并为一个,然后再传递给 xsl:apply-templates
或找到最终元素的替代方法? xsl:for-each-group
是最好的方法吗?
我研究了各种使用方法 variables/arrays 但似乎不符合要求。
你可以改变
<xsl:template match="/">
<xsl:for-each-group select="/*/*/tag[@k='fhrs:id']" group-by="@v">
<xsl:apply-templates select="current-group() [current-group()[2]]"/>
</xsl:for-each-group>
</xsl:template>
到
<xsl:template match="/">
<xsl:variable name="duplicates" as="element()*">
<xsl:for-each-group select="/*/*/tag[@k='fhrs:id']" group-by="@v">
<xsl:sequence select="current-group() [current-group()[2]]"/>
</xsl:for-each-group>
</xsl:variable>
<xsl:apply-templates select="$duplicates"/>
</xsl:template>
至于 last()
的问题,Saxonica 重现了 https://saxonica.plan.io/issues/3122 中报告的问题,我认为在你的情况下你可以通过使用稍微不同的检查来避免使用 last()
position() gt 1
,但在输出内容之前:
<xsl:template match="/*/*/tag">
<xsl:if test="position() gt 1">,</xsl:if>
{
"value" : "<xsl:value-of select="@v"/>"
}
</xsl:template>
<xsl:template match="/">
<xsl:variable name="duplicates" as="element()*">
<xsl:for-each-group select="/*/*/tag[@k='fhrs:id']" group-by="@v">
<xsl:sequence select="current-group() [current-group()[2]]"/>
</xsl:for-each-group>
</xsl:variable>
<xsl:apply-templates select="$duplicates"/>
</xsl:template>
这样你应该能够避免与 last()
相关的错误,但是你应该在序列的项目之间得到一个逗号输出。
使用 SaxonHE 9.7/XPath-2.0
我的XML:
<osm>
<node>
<tag k="fhrs:id" v="204258"/>
<tag k="name" v="King of Wessex"/>
</node>
<node>
<tag k="fhrs:id" v="139245"/>
<tag k="name" v="The Royal Oak"/>
</node>
<node>
<tag k="fhrs:id" v="204258"/>
<tag k="name" v="The Rising Sun"/>
</node>
etc...
</osm>
我正在返回 fhrs:id
的所有重复值 (v=
) 使用:
<xsl:template match="/">
<xsl:for-each-group select="/*/*/tag[@k='fhrs:id']" group-by="@v">
<xsl:apply-templates select="current-group() [current-group()[2]]"/>
</xsl:for-each-group>
</xsl:template>
我正在将输出转换为 geojson 格式。这要求除最后一个元素之外的每个元素都以逗号结尾。在其他例程中,我用它来测试它是否是最后一个:
<xsl:template match="/*/*/tag">
{
...<snip>...
}<xsl:if test="position() < last()">,</xsl:if>
</xsl:template>
但是,因为在这种情况下 xsl:apply-templates
一次只传递两个,所以 geojson 输出中的每个其他元素都缺少一个逗号。
有没有一种方法可以将 xsl:for-each-group
的所有输出合并为一个,然后再传递给 xsl:apply-templates
或找到最终元素的替代方法? xsl:for-each-group
是最好的方法吗?
我研究了各种使用方法 variables/arrays 但似乎不符合要求。
你可以改变
<xsl:template match="/">
<xsl:for-each-group select="/*/*/tag[@k='fhrs:id']" group-by="@v">
<xsl:apply-templates select="current-group() [current-group()[2]]"/>
</xsl:for-each-group>
</xsl:template>
到
<xsl:template match="/">
<xsl:variable name="duplicates" as="element()*">
<xsl:for-each-group select="/*/*/tag[@k='fhrs:id']" group-by="@v">
<xsl:sequence select="current-group() [current-group()[2]]"/>
</xsl:for-each-group>
</xsl:variable>
<xsl:apply-templates select="$duplicates"/>
</xsl:template>
至于 last()
的问题,Saxonica 重现了 https://saxonica.plan.io/issues/3122 中报告的问题,我认为在你的情况下你可以通过使用稍微不同的检查来避免使用 last()
position() gt 1
,但在输出内容之前:
<xsl:template match="/*/*/tag">
<xsl:if test="position() gt 1">,</xsl:if>
{
"value" : "<xsl:value-of select="@v"/>"
}
</xsl:template>
<xsl:template match="/">
<xsl:variable name="duplicates" as="element()*">
<xsl:for-each-group select="/*/*/tag[@k='fhrs:id']" group-by="@v">
<xsl:sequence select="current-group() [current-group()[2]]"/>
</xsl:for-each-group>
</xsl:variable>
<xsl:apply-templates select="$duplicates"/>
</xsl:template>
这样你应该能够避免与 last()
相关的错误,但是你应该在序列的项目之间得到一个逗号输出。