我有这个结构的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>
我需要排序和由参考值/ PO基线,然后复制父节点的每个组线,像在下面的例子。
<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>
如何才能做到这一点?我已经看过了,没有发现任何精确匹配类似的问题,所以很抱歉,如果我忽略了一些东西。感谢帮助。
假设至少XSLT 2,你有for-each-group
,你可以用它来分组和排序,然后你只需要重建strucuture
<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 3的可避免对XSLT 2 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>
<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