XSLT: выбирайте последующие теги в дочерние сегменты до следующего тега. - PullRequest
1 голос
/ 12 февраля 2020

У меня есть следующий ввод XML. Последовательные E_Records являются необязательными, и они должны быть заполнены в L_Record. Я написал приведенную ниже кодировку XSLT. Есть ли какие-либо изменения, которые я должен сделать?

Ввод XML

<?xml version="1.0" encoding="UTF-8"?>
  <Record>
     <H_Record>
        <Rec_Type>H</Rec_Type>
     </H_Record>
     <C_Record>
        <Rec_Type>C</Rec_Type>
     </C_Record>
     <L_Record>
        <Rec_Type>L</Rec_Type>
        <L_Level>2</L_Level>
     </L_Record>
     <E_Record>
        <Rec_Type>E</Rec_Type>
        <E_Qty>3</E_Qty>
     </E_Record>
     <E_Record>
        <Rec_Type>E</Rec_Type>
        <E_Qty>4</E_Qty>
     </E_Record>
     <L_Record>
        <Rec_Type>L</Rec_Type>
        <L_Level>2</L_Level>
     </L_Record>
     <R_Record>
        <Rec_Type>R</Rec_Type>
     </R_Record>
  </Record>
  <Record>
     <H_Record>
        <Rec_Type>H</Rec_Type>
     </H_Record>
     <C_Record>
        <Rec_Type>C</Rec_Type>
     </C_Record>
     <L_Record>
        <Rec_Type>L</Rec_Type>
        <L_Level>2</L_Level>
     </L_Record>
     <L_Record>
        <Rec_Type>L</Rec_Type>
        <L_Level>2</L_Level>
     </L_Record>
     <E_Record>
        <Rec_Type>E</Rec_Type>
        <E_Qty>1</E_Qty>
     </E_Record>
     <E_Record>
        <Rec_Type>E</Rec_Type>
        <E_Qty>2</E_Qty>
     </E_Record>
     <L_Record>
        <Rec_Type>L</Rec_Type>
        <L_Level>2</L_Level>
     </L_Record>
     <E_Record>
        <Rec_Type>E</Rec_Type>
        <E_Qty>5</E_Qty>
     </E_Record>
     <E_Record>
        <Rec_Type>E</Rec_Type>
        <E_Qty>6</E_Qty>
     </E_Record>
     <R_Record>
        <Rec_Type>R</Rec_Type>
     </R_Record>
  </Record>

Ввод XML Я ожидаю

 <Record>
   <H_Record>
        <Rec_Type>H</Rec_Type>
   </H_Record>
   <C_Record>
        <Rec_Type>C</Rec_Type>
   </C_Record>
   <L_Record>
        <Rec_Type>L</Rec_Type>
        <L_Level>2</L_Level>
      <E_Record>
        <Rec_Type>E</Rec_Type>
        <E_Qty>3</E_Qty>
      </E_Record>
      <E_Record>
        <Rec_Type>E</Rec_Type>
        <E_Qty>4</E_Qty>
      </E_Record>
    </L_Record>
    <L_Record>
       <Rec_Type>L</Rec_Type>
       <L_Level>2</L_Level>
    </L_Record>
    <R_Record>
       <Rec_Type>R</Rec_Type>
    </R_Record>
  </Record>
  <Record>
     <H_Record>
        <Rec_Type>H</Rec_Type>
     </H_Record>
     <C_Record>
        <Rec_Type>C</Rec_Type>
     </C_Record>
     <L_Record>
        <Rec_Type>L</Rec_Type>
        <L_Level>2</L_Level>
     </L_Record>
     <L_Record>
        <Rec_Type>L</Rec_Type>
        <L_Level>2</L_Level>      
       <E_Record>
        <Rec_Type>E</Rec_Type>
        <E_Qty>1</E_Qty>
       </E_Record>
       <E_Record>
        <Rec_Type>E</Rec_Type>
        <E_Qty>2</E_Qty>
       </E_Record>
     </L_Record>
     <L_Record>
        <Rec_Type>L</Rec_Type>
        <L_Level>2</L_Level>      
        <E_Record>
          <Rec_Type>E</Rec_Type>
          <E_Qty>5</E_Qty>
        </E_Record>
        <E_Record>
          <Rec_Type>E</Rec_Type>
          <E_Qty>6</E_Qty>
        </E_Record>
    </L_Record>
    <R_Record>
        <Rec_Type>R</Rec_Type>
     </R_Record>
  </Record>

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

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

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

  <xsl:template match="Record">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each-group select="*" group-starting-with="L_Record">
        <xsl:copy>
          <xsl:apply-templates select="@*,node(),current-group()[self::E_Record]"/>          
        </xsl:copy>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

Пожалуйста, помогите мне в этом?
Когда я выполняю вышеуказанный код, C_Record и R_Record удаляются. Как заполнить эти данные в выводе?

1 Ответ

2 голосов
/ 12 февраля 2020

Обычный подход состоит в том, чтобы продолжать использовать for-each-group group-starting-with, но затем внутри добавить дополнительную проверку, есть ли у вас совпадение (например, на L_Record):

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

https://xsltfiddle.liberty-development.net/bFWRApc/1 - это расширение примера кода из вашего предыдущего вопроса.

...