XSLT сортирует и группирует дочерние сегменты и дублирует родительский - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть 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, а затем продублировать родительские узлы для каждой группы строк, как в примере ниже.

<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>

Как это можно сделать?Я искал похожие вопросы, не находя точного соответствия, поэтому извиняюсь, если что-то пропустил.Ценю помощь.

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019
<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

0 голосов
/ 05 февраля 2019

Если принять хотя бы 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 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...