Как создать универсальный XSLT для добавления узлов

#templates #generics #select #xslt #nodes

Вопрос:

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

Входной XML (пример1)

 <?xml version="1.0" encoding="UTF-8"?>

<Order>
    <data1>
        <test>1</test>
        <test2>2</test2>
        <test3>3</test3>
    </data1>
</Order>
 

Это также может быть другой XML <Invoice> -файл или что-то еще.

Требуемая Производительность

 <?xml version="1.0" encoding="UTF-8"?>
<soap:envelope>
<soap:body>
<Order>
    <data1>
        <test>1</test>
        <test2>2</test2>
        <test3>3</test3>
    </data1>
</Order>
</soap:body>
</soap:envelope>
 

С помощью следующего XSLT мне нужно знать, какой узел поступает (заказ или счет), чтобы соответствовать шаблону, но может ли это быть общим?

 <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
<!-- I do not want to specify the node here -->
    <xsl:template match="Order">
        <soap:envelope>
        <soap:body>
            <xsl:copy-of select="*"/>              
        </soap:body>
        </soap:envelope>
    </xsl:template>
  </xsl:stylesheet>
 

Комментарии:

1. поскольку <корень> является динамическим, попробуйте сопоставить сам корень.

Ответ №1:

Вывод, который вы показываете, не является хорошо сформированным XML-документом: вы не можете использовать префикс, не привязав его к пространству имен. Ваш XSLT имеет тот же недостаток и не может быть использован без возникновения ошибки (по крайней мере, с соответствующим процессором).

Я предполагаю, что вы хотите использовать:

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:template match="/">
    <soap:envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
        <soap:body>
            <xsl:copy-of select="."/>              
        </soap:body>
    </soap:envelope>
</xsl:template>

</xsl:stylesheet>
 

чтобы создать действительное сообщение SOAP:

 <?xml version="1.0" encoding="UTF-8"?>
<soap:envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
   <soap:body>
      <Order>
         <data1>
            <test>1</test>
            <test2>2</test2>
            <test3>3</test3>
         </data1>
      </Order>
   </soap:body>
</soap:envelope>
 

Комментарии:

1. Спасибо! да, я пропустил пространство имен в своем исходном сообщении, но это отлично работает. На данный момент не могу проголосовать, но принял ответ.

2. @michael : в чем разница в этом случае, если использовать пространство имен в объявлении таблицы стилей,а не в самом элементе? т. е. <xsl:stylesheet xmlns:soap="---" против <soap:envelope xmlns:soap="---"

3. @sspsujit В этом случае не было бы никакой разницы.

Ответ №2:

вам нужно соответствовать root для этого.

 <xsl:template match="/">
    <soap:envelope>
    <soap:body>
        <xsl:copy-of select="."/>              
    </soap:body>
    </soap:envelope>
</xsl:template>
 

тест: https://xsltfiddle.liberty-development.net/jxWZS7L