Обработка нескольких для цикла в XSLT - PullRequest
1 голос
/ 04 июля 2019

Уважаемые эксперты, мне нужно использовать несколько циклов for в XSLT.

В настоящее время с моим XSLT я генерирую вывод с дополнительными узлами в GroupDetail.

Запрос ввода

  <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
    xmlns:v1="http://xmldefs. ag.com/Applications/eer/V1" xmlns:wsa="http://www.w3.org/2005/08/addressing">
    <SOAP-ENV:Header>
    <wsa:messageId>04383-34380-3439939</wsa:messageId>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
    <v1:ProcessDistr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <v1:Group xmlns:ns2="http://xmldefs.ag.com/DD/Commons">
        <v1:GroupID>437848</v1:GroupID>
        <v1:GroupDetails>
         <v1:GroupDetail>
                <v1:language>De</v1:language>
                <v1:description>Deutsch</v1:description>
         </v1:GroupDetail>
         <v1:GroupDetail>
                <v1:language>En</v1:language>
                <v1:description>English</v1:description>
         </v1:GroupDetail>
        </v1:GroupDetails> 
        <v1:Status>true</v1:Status>
        <v1:Parent>45434554</v1:Parent>
      </v1:Group>
      <v1:Group xmlns:ns2="http://xmldefs.ag.com/DD/Commons">
        <v1:GroupID>437849</v1:GroupID>
        <v1:GroupDetails>
         <v1:GroupDetail>
                <v1:language>Tu</v1:language>
                <v1:description>Turkish</v1:description>
         </v1:GroupDetail>
         <v1:GroupDetail>
                <v1:language>Fr</v1:language>
                <v1:description>French</v1:description>
         </v1:GroupDetail>
        </v1:GroupDetails> 
        <v1:Status>true</v1:Status>
        <v1:Parent>45434555</v1:Parent>
      </v1:Group>
    </v1:ProcessDistr>
    </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>

Вывод получен с другим набором сведений о группе, а также отсутствует «messageId».

Вывод получен:

<?xml version="1.0" encoding="UTF-8"?>
<ProcessDistr >
  <Group >
    <GroupID>437848</GroupID>
     <GroupDetails>
     <GroupDetail>
            <language>De</language>
            <description>Deutsch</description>
     </GroupDetail>
     <GroupDetail>
            <language>En</language>
            <description>English</description>
     </GroupDetail>
      <GroupDetail>
            <language>Tu</language>
            <description>Turkish</description>
     </GroupDetail>
     <GroupDetail>
            <language>Fr</language>
            <description>French</description>
     </GroupDetail>
   </GroupDetails>
    <Status>true</Status>
    <Parent>45434554</Parent>
  </Group>
  <Group >
    <GroupID>437849</GroupID>
    <GroupDetails>
     <GroupDetail>
            <language>De</language>
            <description>Deutsch</description>
     </GroupDetail>
     <GroupDetail>
            <language>En</language>
            <description>English</description>
     </GroupDetail>
      <GroupDetail>
            <language>Tu</language>
            <description>Turkish</description>
     </GroupDetail>
     <GroupDetail>
            <language>Fr</language>
            <description>French</description>
     </GroupDetail>
   </GroupDetails>
    <Status>true</Status>
    <Parent>45434555</Parent>
  </Group>
  <messageId/>
</ProcessDistr>

Это код XSLT, который я разработал

Используемый код XSLT:

 <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="2.0" xmlns:prof="http://ixult.net/ProfileExchange" 
    xmlns:sap="http://www.sap.com/sapxsl" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsltc="http://xml.apache.org/xalan/xsltc" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:v1="http://xmldefs. ag.com/Applications/eer/V1" 
    xmlns:vwsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:ns2="http://xmldefs.vag.com/DD/Commons" 
    exclude-result-prefixes="vwsu v1 ns2 xsi wsa" xmlns:wsa="http://www.w3.org/2005/08/addressing">
       <!-- Output -->
       <xsl:output encoding="UTF-8" indent="yes" method="xml" omit-xml-declaration="yes"/>
       <xsl:strip-space elements="*"/>

                       <xsl:template match="/">


              <xsl:element name="ProcessDistr">
               <xsl:for-each select="//soap:Body/v1:ProcessDistr/v1:Group">
                <xsl:element name="Group">

                    <xsl:element name="GroupID"><xsl:value-of select="v1:GroupID"/></xsl:element>
                     <xsl:element name="GroupDetails">
                        <xsl:for-each select="//v1:GroupDetails/v1:GroupDetail">
                         <xsl:element name="GroupDetail">

                         <xsl:element name="language"><xsl:value-of select="v1:language"/></xsl:element>
                         <xsl:element name="Description">

                          <xsl:value-of select="v1:Description"/></xsl:element>

                         </xsl:element>
                       </xsl:for-each>

                    </xsl:element>

                   <xsl:element name="Status"><xsl:value-of select="v1:Status"/></xsl:element>
                  <xsl:element name="Parent"><xsl:value-of select="v1:Parent"/></xsl:element>

                </xsl:element>                
              </xsl:for-each>
              <xsl:element name="messageId"><xsl:value-of select="wsa:messageID"/>
    </xsl:element>
             </xsl:element>


                    </xsl:template>



    </xsl:stylesheet>

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

    <?xml version="1.0" encoding="UTF-8"?>
    <ProcessDistr >
      <Group >
        <GroupID>437848</GroupID>
         <GroupDetails>
         <GroupDetail>
                <language>De</language>
                <description>Deutsch</description>
         </GroupDetail>
         <GroupDetail>
                <language>En</language>
                <description>English</description>
         </GroupDetail>
       </GroupDetails>
        <Status>true</Status>
        <Parent>45434554</Parent>
      </Group>
      <Group >
        <GroupID>437849</GroupID>
        <GroupDetails>
          <GroupDetail>
                <language>Tu</language>
                <description>Turkish</description>
         </GroupDetail>
         <GroupDetail>
                <language>Fr</language>
                <description>French</description>
         </GroupDetail>
       </GroupDetails>
        <Status>true</Status>
        <Parent>45434555</Parent>
      </Group>
      <messageId>04383-34380-3439939</messageId>
    </ProcessDistr>

Пожалуйста, помогите мне с этим кодом

Большое спасибо.

С наилучшими пожеланиями, Сатиш N

Ответы [ 2 ]

0 голосов
/ 04 июля 2019

Пожалуйста, помогите мне с этим кодом

Дорогой Сатиш,

Основная проблема предоставленного кода не в строке 20, хотя исправление этого помогает получить желаемый результат.

Основная проблема заключается в том, что в коде не используется мощная модель обработки XSLT, с помощью которой решение может быть выражено без каких-либо <xsl:for-each> инструкций. Кроме того, код может быть сокращен и сделан более компактным, понятным и обслуживаемым.

Вот начальное решение (30 строк), которое показывает, как это можно сделать:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:v1="http://xmldefs. ag.com/Applications/eer/V1" xmlns:wsa="http://www.w3.org/2005/08/addressing"
  exclude-result-prefixes="soap-env wsa v1">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

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

  <xsl:template match="/*">
    <xsl:apply-templates select="soap-env:Body"/>
  </xsl:template>

  <xsl:template match="v1:ProcessDistr">
    <ProcessDistr>
      <xsl:apply-templates/>
      <xsl:apply-templates select="/*/soap-env:Header/wsa:messageId"/>
    </ProcessDistr>
  </xsl:template>

  <xsl:template match="v1:* | wsa:*">
   <xsl:element name="{local-name()}">
     <xsl:apply-templates select="node()|@*"/>
   </xsl:element>
  </xsl:template>
  <xsl:template match="soap-env:*"><xsl:apply-templates/></xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу XML:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
    xmlns:v1="http://xmldefs. ag.com/Applications/eer/V1" xmlns:wsa="http://www.w3.org/2005/08/addressing">
    <SOAP-ENV:Header>
        <wsa:messageId>04383-34380-3439939</wsa:messageId>
    </SOAP-ENV:Header>
    <SOAP-ENV:Body>
        <v1:ProcessDistr xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
            <v1:Group xmlns:ns2="http://xmldefs.ag.com/DD/Commons">
                <v1:GroupID>437848</v1:GroupID>
                <v1:GroupDetails>
                    <v1:GroupDetail>
                        <v1:language>De</v1:language>
                        <v1:description>Deutsch</v1:description>
                    </v1:GroupDetail>
                    <v1:GroupDetail>
                        <v1:language>En</v1:language>
                        <v1:description>English</v1:description>
                    </v1:GroupDetail>
                </v1:GroupDetails>
                <v1:Status>true</v1:Status>
                <v1:Parent>45434554</v1:Parent>
            </v1:Group>
            <v1:Group xmlns:ns2="http://xmldefs.ag.com/DD/Commons">
                <v1:GroupID>437849</v1:GroupID>
                <v1:GroupDetails>
                    <v1:GroupDetail>
                        <v1:language>Tu</v1:language>
                        <v1:description>Turkish</v1:description>
                    </v1:GroupDetail>
                    <v1:GroupDetail>
                        <v1:language>Fr</v1:language>
                        <v1:description>French</v1:description>
                    </v1:GroupDetail>
                </v1:GroupDetails>
                <v1:Status>true</v1:Status>
                <v1:Parent>45434555</v1:Parent>
            </v1:Group>
        </v1:ProcessDistr>
    </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

желаемый, правильный результат получается :

<ProcessDistr>
   <Group>
      <GroupID>437848</GroupID>
      <GroupDetails>
         <GroupDetail>
            <language>De</language>
            <description>Deutsch</description>
         </GroupDetail>
         <GroupDetail>
            <language>En</language>
            <description>English</description>
         </GroupDetail>
      </GroupDetails>
      <Status>true</Status>
      <Parent>45434554</Parent>
   </Group>
   <Group>
      <GroupID>437849</GroupID>
      <GroupDetails>
         <GroupDetail>
            <language>Tu</language>
            <description>Turkish</description>
         </GroupDetail>
         <GroupDetail>
            <language>Fr</language>
            <description>French</description>
         </GroupDetail>
      </GroupDetails>
      <Status>true</Status>
      <Parent>45434555</Parent>
   </Group>
   <messageId>04383-34380-3439939</messageId>
</ProcessDistr>

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

0 голосов
/ 04 июля 2019

Основная проблема с вашим XSLT заключается в следующем (строка 20):

<xsl:for-each select="//v1:GroupDetails/v1:GroupDetail">

Путь, начинающийся с //, выбирает всех потомков корневого узла независимо от текущего контекста. Вам нужно только обработать потомков текущего v1:Group, поэтому вам нужно изменить его на:

<xsl:for-each select="v1:GroupDetails/v1:GroupDetail">

Обратите внимание, что в XML учитывается регистр:

<xsl:value-of select="v1:Description"/>

не вернет значение элемента с именем v1:description.


Я бы также рекомендовал использовать буквенные элементы результата вместо инструкции xsl:element. Используйте xsl:element, когда необходимо определить имя элемента во время выполнения.

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