我有一个具有以下结构的xml:
<Order>
<Top>
</Top>
<Body>
<Line>
<Ref>
<PO>1</PO>
</Ref>
</Line>
<Line>
<Ref>
<PO>1</PO>
</Ref>
</Line>
<Line>
<Ref>
<PO>3</PO>
</Ref>
</Line>
<Line>
<Ref>
<PO>3</PO>
</Ref>
</Line>
<Line>
<Ref>
<PO>2</PO>
</Ref>
</Line>
<Line>
<Ref>
<PO>2</PO>
</Ref>
</Line>
</Body>
</Order>
我需要按Ref / PO对Line进行排序和分组,然后为每组Line复制父节点,如下例所示。
<Order>
<Top>
</Top>
<Body>
<Line>
<Ref>
<PO>1</PO>
</Ref>
</Line>
<Line>
<Ref>
<PO>1</PO>
</Ref>
</Line>
</Body>
</Order>
<Order>
<Top>
</Top>
<Body>
<Line>
<Ref>
<PO>2</PO>
</Ref>
</Line>
<Line>
<Ref>
<PO>2</PO>
</Ref>
</Line>
</Body>
</Order>
<Order>
<Top>
</Top>
<Body>
<Line>
<Ref>
<PO>3</PO>
</Ref>
</Line>
<Line>
<Ref>
<PO>3</PO>
</Ref>
</Line>
</Body>
</Order>
这怎么办?我一直在寻找类似的问题,但没有找到完全匹配的内容,因此,如果我忽略了某些内容,请向我们道歉。感谢帮助。
答案 0 :(得分:0)
假设至少XSLT 2在for-each-group
所在的位置,则可以使用它进行分组和排序,然后只需重构结构
<xsl:template match="Body">
<xsl:for-each-group select="Line" group-by="Ref/PO">
<xsl:sort select="xs:integer(current-grouping-key())"/>
<xsl:copy select="../..">
<xsl:copy-of select="* except Body"/>
<Body>
<xsl:copy-of select="current-group()"/>
</Body>
</xsl:copy>
</xsl:for-each-group>
</xsl:template>
https://xsltfiddle.liberty-development.net/bnnZVK/1包含完整的示例
<?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"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-skip"/>
<xsl:output indent="yes"/>
<xsl:template match="Body">
<xsl:for-each-group select="Line" group-by="Ref/PO">
<xsl:sort select="xs:integer(current-grouping-key())"/>
<xsl:copy select="../..">
<xsl:copy-of select="* except Body"/>
<Body>
<xsl:copy-of select="current-group()"/>
</Body>
</xsl:copy>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
使用XSLT 3(但是对于带有xsl:copy select
的XSLT 2,可以避免使用XSLT 3独有的xsl:element
)
<xsl:template match="Body">
<xsl:for-each-group select="Line" group-by="Ref/PO">
<xsl:sort select="xs:integer(current-grouping-key())"/>
<xsl:element name="{name(../..)}" namespace="{namespace-uri(../..)}">
<xsl:copy-of select="../../(* except Body)"/>
<Body>
<xsl:copy-of select="current-group()"/>
</Body>
</xsl:element>
</xsl:for-each-group>
</xsl:template>
答案 1 :(得分:0)
<xsl:template match="Body">
<xsl:for-each-group select="Line" group-by="Ref/PO">
<xsl:sort select="current-grouping-key()"/>
<xsl:element name="order">
<xsl:element name="top"></xsl:element>
<Body>
<xsl:copy-of select="current-group()"/>
</Body>
</xsl:element>
</xsl:for-each-group>
xslt 2.0