Вывод пространства имен с XSLT 1.0, вызывающий проблемы - PullRequest
0 голосов
/ 12 октября 2010

Я использую XSLT 1.0 для преобразования XML.

Я не совсем уверен, как лучше объяснить это, поэтому приведу несколько примеров.

Мой входной XML содержит специализацию, использующую объявление типа xsi :. Смотрите узел полезной нагрузки:

<ns0:RootNode xmlns:ns0="namespace1" xmlns:ns1="namespace2" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode>Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

Когда я отправляю это через мой XSLT (предположим, копия 1 к 1), я получаю следующий вывод

<ns0:RootNode xmlns:ns0="namespace1" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode xmlns:ns1="namespace2">Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

Обратите внимание, что пространство имен ns1 было присоединено к отдельным узлам внутри узла полезной нагрузки. В большинстве случаев это было бы хорошо, однако мне нужно, чтобы это объявление происходило раньше, то есть на корневом узле, поскольку это делает определение xsi: type на узле полезной нагрузки недопустимым, поскольку в этот момент сериализатор не знает о пространстве имен ns1 , что препятствует правильному разбору в нисходящем направлении.

Что я могу сделать, чтобы заставить это пространство имен выводиться немного раньше?

Отредактированный код XSLT:

  <!-- Replace The ESBMessage node with the SOAP method -->
  <xsl:template match="s1:ESBMessage" mode="copy">
    <s0:SendESBMessage>
      <s0:msg>
        <xsl:apply-templates select="*" mode="copy"/>
      </s0:msg>
    </s0:SendESBMessage>
  </xsl:template>

  <!-- Generic Copy -->
  <xsl:template match="*" mode="copy">
    <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates mode="copy"/>
    </xsl:element>
  </xsl:template>

1 Ответ

1 голос
/ 12 октября 2010

Обратите внимание, что пространство имен ns1 было прикреплен к отдельным узлам в узле полезной нагрузки. В большинстве случаев это было бы хорошо, однако мне нужно эта декларация произойдет раньше, т.е. на корневом узле, так как это делает xsi: определение типа в полезной нагрузке неверный узел, потому что в этот момент сериализатор не знает о Пространство имен ns1, которое мешает правильно Разбор вниз по течению.

Что я могу сделать, чтобы заставить это пространство имен выводиться чуть раньше?

Вы можете сделать что-то очень простое: покажите нам свой код !

Ваше утверждение о том, что "простая копия" теряет одно из пространств имен верхнего узла, неверно для следующих двух "простых копий":

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

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

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

<ns0:RootNode xmlns:ns0="namespace1" xmlns:ns1="namespace2" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode>Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

результат идентичен :

<ns0:RootNode xmlns:ns0="namespace1" xmlns:ns1="namespace2" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
  <ns0:Payload xsi:type="ns1:SpecialPayload">
    <ns1:InnerNode>Hello</ns1:InnerNode>
  </ns0:Payload>
</ns0:RootNode>

Вот вторая «простая копия»:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>

результат снова идентичен исходному документу XML .

...