Как использовать xslt для добавления пространств имен в xml - PullRequest
1 голос
/ 01 декабря 2009

У меня есть веб-служба SOAP, которая определена сначала контрактом - XML-запрос и ответ определяются xsds, которые используют несколько различных пространств имен, и в xsds определены сотни элементов. Однако веб-служба вызывает устаревший уровень, который не использует пространства имен в XML. Поэтому у меня есть слой преобразования между веб-сервисом и унаследованным уровнем, который использует xslt для преобразования XML-запроса и ответа. На пути в слое преобразования используется xslt для удаления префиксов пространства имен из запроса xml, который работает нормально, поскольку существует только небольшое количество префиксов пространства имен для сопоставления.

Однако на выходе мне нужен xslt, который добавит префиксы пространства имен обратно в ответ, и я не уверен, как это сделать. Ответ может состоять из десятков различных типов элементов; который может принадлежать одному из нескольких различных пространств имен в xsds. Например, у меня может быть такой ответ:

<order>
  <item name="table"/>
  <customer name="jim"/>
</order>

Мне нужно преобразовать это в:

<order 
  xmlns:types1="http://types1.company.com" xmlns:types2="http://types2.company.com">
  <types1:item name="table"/>
  <types2:customer name="jim"/>
</order>

Единственный способ сделать это - создать в xslt большую таблицу, которая соответствует имени элемента в ответе (например, "item", "customer") и префиксу, который следует использовать?

Или было бы лучше исправить некоторый код, который загружается в xsd как xml, а затем сопоставлять элементы ответа с элементами в xsd и таким образом получать правильное пространство имен?

1 Ответ

1 голос
/ 01 декабря 2009

Я думаю, что-то подобное может сделать работу:

<xsl:stylesheet 
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

  <!-- the identity template to copy everything as it is -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
  </xsl:template>

  <!-- elements are re-created with a namespace -->
  <xsl:template match="*">

    <xsl:variable name="ns-uri">
      <xsl:choose>
        <xsl:when test="name() = 'item' and name(..) = 'order'">
          <xsl:text>http://types1.company.com</xsl:text>
        </xsl:when>
        <xsl:when test="name() = 'customer' and name(..) = 'order'">
          <xsl:text>http://types2.company.com</xsl:text>
        </xsl:when>
        <!-- otherwise: nothing -->
      </xsl:choose>
    </xsl:variable>

    <!-- create the element with the correct namespace -->    
    <xsl:element name="{name()}" namespace="{$ns-uri}">
      <xsl:apply-templates select="node() | @*" />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

Вывод для меня:

<order>
  <item name="table" xmlns="http://types1.company.com"></item>
  <customer name="jim" xmlns="http://types2.company.com"></customer>
</order>

Что у вас есть, просто без префиксов. Информационный набор точно такой же.

...