Добавить инкрементные элементы "lineNumber" в XML с использованием XSLT 1.0 - PullRequest
0 голосов
/ 12 марта 2019

Как добавить элемент <lineNumber> в файл XML с помощью XSLT?

Я хотел бы добавлять новый элемент "lineNumber" внутри каждого вхождения элемента <TXT> в пределах внешнего элемента <GRP> или <ITEM>.

Текст элемента <lineNumber> должен быть числом, которое увеличивается на единицу для каждого вхождения <TXT>, начиная с 1.

Два внешних элемента <GRP> и <ITEM> должны обрабатываться отдельно.

Пример входного XML:

<?xml version="1.0"?>
<SEEDELFOR>
    <Test/>
    <CNT>        
        <GRP>
            <IDENTIFIER_BY></IDENTIFIER_BY>            
            </ADD>
            <TXT>
                <QUALIFIER>AAA</QUALIFIER>
                <TEXT>Test AAA</TEXT>
            </TXT>
            <TXT>
                <QUALIFIER>AAA</QUALIFIER>
                <TEXT>rtetertertret</TEXT>
            </TXT>          
            <ITEM>
                <LINE_ITEM_NUMBER>1</LINE_ITEM_NUMBER>
                <TXT>
                 <QUALIFIER>LIN</QUALIFIER>
                <TEXT>Test LIN</TEXT>
            </TXT>
            </ITEM>
            <ITEM>               
                <LINE_ITEM_NUMBER>2</LINE_ITEM_NUMBER>
                <TXT>
                    <QUALIFIER>LIN</QUALIFIER>
                    <TEXT>Test LIN</TEXT>
                </TXT>
                <TXT>                    
                    <QUALIFIER>LIN</QUALIFIER>
                    <TEXT>sdfsdfsfsf</TEXT>
                </TXT>
            </ITEM>
        </GRP>
    </CNT>
</SEEDELFOR>

Правильный вывод должен быть:

<?xml version="1.0"?>
<SEEDELFOR>
    <Test/>
    <CNT>        
        <GRP>
            <IDENTIFIER_BY></IDENTIFIER_BY>            
            </ADD>
            <TXT>
                <LineNum>1</LineNum>
                <QUALIFIER>AAA</QUALIFIER>
                <TEXT>Test AAA</TEXT>
            </TXT>
            <TXT>
                <LineNum>2</LineNum>
                <QUALIFIER>AAA</QUALIFIER>
                <TEXT>rtetertertret</TEXT>
            </TXT>          
            <ITEM>
                <LINE_ITEM_NUMBER>1</LINE_ITEM_NUMBER>
                <TXT>
                <LineNum>1</LineNum>
                <QUALIFIER>LIN</QUALIFIER>
                <TEXT>Test LIN</TEXT>
            </TXT>
            </ITEM>
            <ITEM>               
                <LINE_ITEM_NUMBER>2</LINE_ITEM_NUMBER>
                <TXT>
                    <LineNum>1</LineNum>
                    <QUALIFIER>LIN</QUALIFIER>
                    <TEXT>Test LIN</TEXT>
                </TXT>
                <TXT>
                    <LineNum>2</LineNum>
                    <QUALIFIER>LIN</QUALIFIER>
                    <TEXT>sdfsdfsfsf</TEXT>
                </TXT>
            </ITEM>
        </GRP>
    </CNT>
</SEEDELFOR>

А вот мой XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>
    
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

<xsl:template match="GRP">
    <xsl:copy>
    <!--copy content of ST from ADD to GRP, so it can be used for a different delivery address -->
      <xsl:for-each select="./ADD">
            <xsl:if test="./QUALIFIER='ST'">
                <xsl:copy-of select="PARTY_NAME_1" />
                <xsl:copy-of select="STREET_1" />
                <xsl:copy-of select="CITY" />
                <xsl:copy-of select="POSTAL_CODE" />
                <xsl:copy-of select="COUNTRY_CODE" />
            </xsl:if>
        </xsl:for-each>
    <!--copy BGM from CNT to GRP, so we can set the SalesOriginId correctly -->
      <xsl:copy-of select="../BGM" />
    <!--copy the data from ADD/CONTACT with Qualifier EM, TE, FX to GRP, so it can be used in the mapping to set EMAIL, Tel or Fax from Customer -->
        <xsl:for-each select ="./ADD/CONTACT">
         <xsl:if test="./QUALIFIER='EM'">          
  <CONTACT_EMAIL>
  <xsl:value-of select="NUMBER"/>      
  </CONTACT_EMAIL>
       </xsl:if>
         <xsl:if test="./QUALIFIER='TE'">          
  <CONTACT_TEL>
  <xsl:value-of select="NUMBER"/>      
  </CONTACT_TEL>
       </xsl:if>
         <xsl:if test="./QUALIFIER='FX'">          
  <CONTACT_FAX>
  <xsl:value-of select="NUMBER"/>      
  </CONTACT_FAX>
       </xsl:if>
      </xsl:for-each>    
    <!--copy all other nodes-->
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="GRP/ITEM">
    <xsl:copy>
     <!--copy all other nodes-->
      <xsl:apply-templates select="@* | node()"/>   
	<!-- check, if TXT = LIN, if yes, build some new Segment "TXT_001" -->
     <xsl:for-each select="./TXT">
            <xsl:if test="./QUALIFIER='LIN'">
            <TXT_001>
                <xsl:copy-of select="QUALIFIER"/>
                <xsl:copy-of select="TEXT"/>
            </TXT_001>
	<!-- check, if TXT = DEL, if yes, build some new Segment "TXT_001" -->
            </xsl:if>
            <xsl:if test="./QUALIFIER='DEL'">
            <TXT_001>
                <xsl:copy-of select="QUALIFIER"/>
                <xsl:copy-of select="TEXT"/>
            </TXT_001>
            </xsl:if>
        </xsl:for-each>   
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

1 Ответ

1 голос
/ 13 марта 2019

Попробуйте использовать xsl:number.Например, следующая таблица стилей:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

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

</xsl:stylesheet>

, примененная к правильно сформированному (!) примеру ввода:

XML

<SEEDELFOR>
    <Test/>
    <CNT>        
        <GRP>
            <IDENTIFIER_BY></IDENTIFIER_BY>            
            <TXT>
                <QUALIFIER>AAA</QUALIFIER>
                <TEXT>Test AAA</TEXT>
            </TXT>
            <TXT>
                <QUALIFIER>AAA</QUALIFIER>
                <TEXT>rtetertertret</TEXT>
            </TXT>          
            <ITEM>
                <LINE_ITEM_NUMBER>1</LINE_ITEM_NUMBER>
                <TXT>
                 <QUALIFIER>LIN</QUALIFIER>
                <TEXT>Test LIN</TEXT>
            </TXT>
            </ITEM>
            <ITEM>               
                <LINE_ITEM_NUMBER>2</LINE_ITEM_NUMBER>
                <TXT>
                    <QUALIFIER>LIN</QUALIFIER>
                    <TEXT>Test LIN</TEXT>
                </TXT>
                <TXT>                    
                    <QUALIFIER>LIN</QUALIFIER>
                    <TEXT>sdfsdfsfsf</TEXT>
                </TXT>
            </ITEM>
        </GRP>
    </CNT>
</SEEDELFOR>

даст:

Результат

<?xml version="1.0" encoding="UTF-8"?>
<SEEDELFOR>
   <Test/>
   <CNT>
      <GRP>
         <IDENTIFIER_BY/>
         <TXT>
            <LineNum>1</LineNum>
            <QUALIFIER>AAA</QUALIFIER>
            <TEXT>Test AAA</TEXT>
         </TXT>
         <TXT>
            <LineNum>2</LineNum>
            <QUALIFIER>AAA</QUALIFIER>
            <TEXT>rtetertertret</TEXT>
         </TXT>
         <ITEM>
            <LINE_ITEM_NUMBER>1</LINE_ITEM_NUMBER>
            <TXT>
               <LineNum>1</LineNum>
               <QUALIFIER>LIN</QUALIFIER>
               <TEXT>Test LIN</TEXT>
            </TXT>
         </ITEM>
         <ITEM>
            <LINE_ITEM_NUMBER>2</LINE_ITEM_NUMBER>
            <TXT>
               <LineNum>1</LineNum>
               <QUALIFIER>LIN</QUALIFIER>
               <TEXT>Test LIN</TEXT>
            </TXT>
            <TXT>
               <LineNum>2</LineNum>
               <QUALIFIER>LIN</QUALIFIER>
               <TEXT>sdfsdfsfsf</TEXT>
            </TXT>
         </ITEM>
      </GRP>
   </CNT>
</SEEDELFOR>
...