Изменить иерархию узла xml на основе вхождения - PullRequest
0 голосов
/ 12 апреля 2019

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

Оплата, перевод, трейлер может повторяться в формате XML.Но за каждой выплатой последует n номеров узлов перевода.где на выходе.Оплата должна содержать все узлы перевода чуть ниже него.

Я пытался использовать код XSLT, но каким-то образом я не получил ожидаемый результат.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output  method="xml" encoding='UTF-8'/>
<!--Identity template, 
        provides default behavior that copies all content into the output -->

      <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:for-each select="pay">
    <xsl:template match="Remit">
        <xsl:value-of select="."/>
        </xsl:template>
    </xsl:for-each>


</xsl:stylesheet>

Ввод -

<?xml version="1.0" encoding="utf-8"?>
<Message>
<Record>
    <Header>
        <H></H>
    </Header>
    <Trailer>
        <AA>1</AA>
    </Trailer>
    <Pay>
        <BB>1</BB>
        <amount>11</amount>
    </Pay>
    <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
    </Remit>
    <Trailer>
        <AA>1</AA>
    </Trailer>
    <Pay>
        <BB>1</BB>
        <amount>78</amount>
    </Pay>
    <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
    </Remit>
    <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
    </Remit>
    <Trailer>
        <AA>1</AA>
    </Trailer>
</Record>
</Message>

ожидаемый вывод:

<?xml version="1.0" encoding="utf-8"?>
<Message>
<Record>
    <Header>
        <H>1</H>
    </Header>`enter code here`
    <Trailer>
        <AA>1</AA>
    </Trailer>
    <Pay>
        <BB>1</BB>
        <amount>11</amount>
        <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
            </Remit>
    </Pay>
    <Trailer>
        <AA>1</AA>
    </Trailer>
    <Pay>
        <BB>1</BB>
        <amount>78</amount>
            <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
            </Remit>
            <Remit>
        <Type>30</Type>
        <Transaction>I</Transaction>
            </Remit>
    </Pay>
    <Trailer>
        <AA>1</AA>
    </Trailer>
</Record>
</Message>

1 Ответ

0 голосов
/ 12 апреля 2019

Простой вариант использования для for-each-group group-starting-with (https://www.w3.org/TR/xslt20/#xsl-for-each-group):

<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:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="Record">
      <xsl:copy>
          <xsl:for-each-group select="*" group-starting-with="Pay">
              <xsl:choose>
                  <xsl:when test="self::Pay">
                      <xsl:copy>
                          <xsl:apply-templates select="node(), current-group()[self::Remit]"/>
                      </xsl:copy>
                      <xsl:apply-templates select="(current-group() except .)[not(self::Remit)]"/>
                  </xsl:when>
                  <xsl:otherwise>
                      <xsl:apply-templates select="current-group()"/>
                  </xsl:otherwise>
              </xsl:choose>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / 3NJ38Zm

Для процессора XSLT 2 замените объявление xsl:mode на свой шаблон идентификации

  <xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>
...