XSLT - нужен для копирования нескольких пространств имен - PullRequest
2 голосов
/ 17 сентября 2011

У меня есть следующий XML. Я должен включить тело мыла под мыльным конвертом.

<headers>
    <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:def="http://lmn" xmlns:abc="http://xyz"><soapenv:Header><abc:Security>    <abc:UsernameToken>
    <abc:Username>abc</abc:Username>
                        <abc:Password>pwd</abc:Password>
                    </abc:UsernameToken>
            </abc:Security>
        </soapenv:Header> 
    </soapenv:Envelope>
 </headers>

Мой вывод должен быть как

     <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:def="http://lmn" xmlns:abc="http://xyz">
         <soapenv:Header>
            <abc:Security>
                    <abc:UsernameToken>
                        <abc:Username>abc</abc:Username>
                        <abc:Password>pwd</abc:Password>
                    </abc:UsernameToken>
            </abc:Security>
        </soapenv:Header> 
        <soapenv:Body><a><b></b><c></c></a></soapenv:Body>
     </soapenv:Envelope>

Ниже мой XSL.

 <?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl" xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:soap="http://www.w3.org/2003/05/soap-envelope" exclude-result-prefixes="xd soap soapenv">
 <xsl:template match="/">
         <xsl:variable name="envNode"><xsl:copy-of select="name(headers/*)"/></xsl:variable>
         <xsl:choose>
             <xsl:when test="contains($envNode,'soapenv')">
                 <xsl:element name="{name(headers/*)}">                   
                     <xsl:copy-of select="headers/soapenv:Envelope/*"/>
                     <xsl:element name="soapenv:Body">
                         <a><b></b><c></c></a>
                     </xsl:element>
                 </xsl:element>
             </xsl:when>
             <xsl:otherwise>
                <xsl:element name="{name(soapOptions/headers/*)}">                   
            <xsl:copy-of select="soapOptions/headers/soap:Envelope/*"/>
            <xsl:element name="soap:Body">
                 <a><b></b><c></c></a>
            </xsl:element>
             </xsl:element>
            </xsl:otherwise>
         </xsl:choose>
  </xsl:template> 

Я получаю следующий вывод.

  <soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
    <soapenv:Header xmlns:def="http://lmn" xmlns:abc="http://xyz"">
            <abc:Security>
                    <abc:UsernameToken>
                        <abc:Username>abc</abc:Username>
                        <abc:Password>pwd</abc:Password>
                    </abc:UsernameToken>
            </abc:Security>
        </soapenv:Header>
        <soapenv:Body><a><b/><c/></a></soapenv:Body>
 </soapenv:Envelope>

Я хочу скопировать все пространства имен, которые есть в узле soapenv: Envelope, в один и тот же узел. Но это копируется в soapenv: Header. Я пробовал много опций namespace вместе с namespace в name элемента в XSL. Может ли кто-нибудь помочь мне в этом.

Заранее спасибо, Najma

Ответы [ 2 ]

2 голосов
/ 17 сентября 2011

Добавить под объявлением элемента:

 <xsl:copy-of select="headers/*/namespace::*"/>

Это скопирует требуемые пространства имен в правильный элемент, что не позволит процессору XSLT объявить их в других местах.


Проверка XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">

    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:element name="{name(headers/*)}">
            <xsl:copy-of select="headers/*/namespace::*"/>
            <xsl:copy-of select="headers/soapenv:Envelope/*"/>
            <xsl:element name="soapenv:Body">
                <a><b></b><c></c></a>
            </xsl:element>
        </xsl:element>

    </xsl:template>

</xsl:stylesheet>

производит:

<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope" xmlns:def="http://lmn" xmlns:abc="http://xyz">
   <soapenv:Header>
      <abc:Security>
         <abc:UsernameToken>
            <abc:Username>abc</abc:Username>
            <abc:Password>pwd</abc:Password>
         </abc:UsernameToken>
      </abc:Security>
   </soapenv:Header>
   <soapenv:Body>
      <a>
         <b/>
         <c/>
      </a>
   </soapenv:Body>
</soapenv:Envelope>

Однако, если вы можете изменить свою таблицу стилей, я бы использовал что-то более простое, например:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">

    <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="headers">
        <xsl:apply-templates select="node()"/>
    </xsl:template>

    <xsl:template match="soapenv:Header">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
            <soapenv:Body>
                <a><b></b><c></c></a>
            </soapenv:Body>
    </xsl:template>

</xsl:stylesheet>
1 голос
/ 17 сентября 2011

Используйте, пожалуй, самое короткое, простое и стандартизированное решение :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
 <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="soapenv:Envelope">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
   <soapenv:Body><a><b/><c/></a></soapenv:Body>
  </xsl:copy>
 </xsl:template>
</xsl:stylesheet>

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

<headers>
    <soapenv:Envelope
      xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
      xmlns:def="http://lmn" xmlns:abc="http://xyz">
        <soapenv:Header>
            <abc:Security>
                <abc:UsernameToken>
                    <abc:Username>abc</abc:Username>
                    <abc:Password>pwd</abc:Password>
                </abc:UsernameToken>
            </abc:Security>
        </soapenv:Header>
    </soapenv:Envelope>
</headers>

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

<headers>
   <soapenv:Envelope
    xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope"
    xmlns:def="http://lmn" xmlns:abc="http://xyz">
      <soapenv:Header>
         <abc:Security>
            <abc:UsernameToken>
               <abc:Username>abc</abc:Username>
               <abc:Password>pwd</abc:Password>
            </abc:UsernameToken>
         </abc:Security>
      </soapenv:Header>
      <soapenv:Body>
         <a>
            <b/>
            <c/>
         </a>
      </soapenv:Body>
   </soapenv:Envelope>
</headers>

Объяснение

  1. Правило / шаблон копирует каждый узел "как есть" .

  2. Существует только один шаблон, переопределяющий правило идентификации. Он соответствует soapenv:Envelope. Обработка очень похожа на обработку шаблона идентификации (соответствующий элемент «копируется мелко, а все его потомки копируются в его теле), но кроме того, новый soapenv:Body также вывод.

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