XSLT排序和分组儿童片段和重复父

问题描述 投票:0回答:2

我有这个结构的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个回答
0
投票

假设至少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>

http://xsltransform.net/pNEhB31


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

© www.soinside.com 2019 - 2024. All rights reserved.