如何按类似源节点生成所需的 XML 输出分组和排序?
How do I produce the required XML output grouping and sorting by like source nodes?
鉴于此来源 XML:
<output>
<report>
<C01>
<InvID>001</InvID>
<Daily>
<row id="0000">1</row>
<row id="0001">2</row>
<row id="0002">5</row>
<row id="0003">4</row>
</Daily>
</C01>
<C02>
<InvID>002</InvID>
<Daily>
<row id="0000">4</row>
<row id="0001">3</row>
<row id="0002">2</row>
<row id="0003">5</row>
</Daily>
</C02>
<C03>
<InvID>001</InvID>
<Daily>
<row id="0000">3</row>
<row id="0001">7</row>
<row id="0002">2</row>
<row id="0003">4</row>
</Daily>
</C03>
<report>
<output>
我怎样才能产生这个输出:
<Data invID=001>
<Value>1</Value>
<Value>2</Value>
<Value>5</Value>
<Value>4</Value>
<Value>3</Value>
<Value>7</Value>
<Value>2</Value>
<Value>4</Value>
</Data>
<Data invID=002>
<Value>4</Value>
<Value>3</Value>
<Value>2</Value>
<Value>5</Value>
</Data>
我一直在尝试用这样的东西作为基础,但是感觉都不对:
<xsl:template match="output/report">
<xsl:for-each select="*[starts-with(name(), 'C') and InvID != '']">
<xsl:sort select="InvID" />
<xsl:element name="Data">
<xsl:attribute name="invID">
<xsl:value-of select="InvID" />
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:template>
我需要聚合共享一个公共 InvID
的所有项目,为该组源元素输出单个 Data
元素,然后输出它们的所有 row
元素值进入 Data
元素 (Value
) 的子元素。
这可以在 XPath 1.0 中完成吗?
正如我在评论中所建议的那样,您正在寻找的技术称为 Muenchian 分组。这通过定义一个 key 将相关节点组合在一起,然后使用 generate-id
或 count
的技巧来构造一个由一个 "representative" 每个组的节点。在您的情况下,由于您要组合在一起的节点具有不同的名称,因此您必须对匹配模式更具创意,但原理是相同的:
<xsl:key name="groupByInv" match="*[InvID]" use="InvID" />
在这里,我对具有 InvID
子元素的任何元素(无论名称如何)感兴趣,我想根据 InvID
值将它们组合在一起。现在实际的分组很简单:
<xsl:template match="output/report">
<xsl:for-each select="*[InvID][generate-id() =
generate-id(key('groupByInv', InvID)[1])]">
<Data invID="{InvID}">
<!-- process all the rows under all the elements in the current group -->
<xsl:apply-templates select="key('groupByInv', InvID)/Daily/row" />
</Data>
</xsl:for-each>
</xsl:template>
<xsl:template match="row">
<Value><xsl:value-of select="."/></Value>
</xsl:template>
鉴于此来源 XML:
<output>
<report>
<C01>
<InvID>001</InvID>
<Daily>
<row id="0000">1</row>
<row id="0001">2</row>
<row id="0002">5</row>
<row id="0003">4</row>
</Daily>
</C01>
<C02>
<InvID>002</InvID>
<Daily>
<row id="0000">4</row>
<row id="0001">3</row>
<row id="0002">2</row>
<row id="0003">5</row>
</Daily>
</C02>
<C03>
<InvID>001</InvID>
<Daily>
<row id="0000">3</row>
<row id="0001">7</row>
<row id="0002">2</row>
<row id="0003">4</row>
</Daily>
</C03>
<report>
<output>
我怎样才能产生这个输出:
<Data invID=001>
<Value>1</Value>
<Value>2</Value>
<Value>5</Value>
<Value>4</Value>
<Value>3</Value>
<Value>7</Value>
<Value>2</Value>
<Value>4</Value>
</Data>
<Data invID=002>
<Value>4</Value>
<Value>3</Value>
<Value>2</Value>
<Value>5</Value>
</Data>
我一直在尝试用这样的东西作为基础,但是感觉都不对:
<xsl:template match="output/report">
<xsl:for-each select="*[starts-with(name(), 'C') and InvID != '']">
<xsl:sort select="InvID" />
<xsl:element name="Data">
<xsl:attribute name="invID">
<xsl:value-of select="InvID" />
</xsl:attribute>
</xsl:element>
</xsl:for-each>
</xsl:template>
我需要聚合共享一个公共 InvID
的所有项目,为该组源元素输出单个 Data
元素,然后输出它们的所有 row
元素值进入 Data
元素 (Value
) 的子元素。
这可以在 XPath 1.0 中完成吗?
正如我在评论中所建议的那样,您正在寻找的技术称为 Muenchian 分组。这通过定义一个 key 将相关节点组合在一起,然后使用 generate-id
或 count
的技巧来构造一个由一个 "representative" 每个组的节点。在您的情况下,由于您要组合在一起的节点具有不同的名称,因此您必须对匹配模式更具创意,但原理是相同的:
<xsl:key name="groupByInv" match="*[InvID]" use="InvID" />
在这里,我对具有 InvID
子元素的任何元素(无论名称如何)感兴趣,我想根据 InvID
值将它们组合在一起。现在实际的分组很简单:
<xsl:template match="output/report">
<xsl:for-each select="*[InvID][generate-id() =
generate-id(key('groupByInv', InvID)[1])]">
<Data invID="{InvID}">
<!-- process all the rows under all the elements in the current group -->
<xsl:apply-templates select="key('groupByInv', InvID)/Daily/row" />
</Data>
</xsl:for-each>
</xsl:template>
<xsl:template match="row">
<Value><xsl:value-of select="."/></Value>
</xsl:template>