Изменение значения пространства имен в XSL-преобразовании? - PullRequest
2 голосов
/ 22 октября 2009

Я не уверен, возможно ли это, так как я очень плохо знаком с XSLT и прочим, но, возможно, некоторые из вас могли бы помочь мне здесь? Это немного сложно, и я не нашел ничего подобного в интернете:

Проблема в том, что у меня есть входной xml с объявленными пространствами имен и всем, и мне нужно только внести в него небольшие изменения (добавление или удаление атрибутов или перемещение их в другие места). Но в то же время я должен обновить ссылки на пространство имен в теге документа документа. Так, например, входной xml может выглядеть примерно так:

<order
  xmlns="some.url.01"
  xmlns:ns2="some.other.url"
  xmlns:ns3="another.one"
>
  <orderEntry>
    <orderControl>
      <mandant>test</mandant>
      <businessUnit>test</businessUnit>
      <inboundChannel>test</inboundChannel>
      <timestamp>timestamp</timestamp>
      <requestedDocuments>
        <ns2:document>orderForm</ns2:document>
      </requestedDocuments>
    </orderControl>
  </orderEntry>
</order>

Полученный XML должен выглядеть следующим образом:

<order
  xmlns="some.url.02"
  xmlns:ns2="some.other.url.02"
  xmlns:ns3="another.one.02"
>
  <orderEntry>
    <orderControl>
      <mandant>test</mandant>
      <businessUnit>test</businessUnit>
      <inboundChannel>test</inboundChannel>
      <!-- deleted timestamp for example -->
      <requestedDocuments>
        <ns2:document>orderForm</ns2:document>
      </requestedDocuments>
    </orderControl>
  </orderEntry>
</order>

но единственное, что я получаю:

<order
  xmlns="some.url.02"
>
  <orderEntry>
    <orderControl>
      <mandant>test</mandant>
      <businessUnit>test</businessUnit>
      <inboundChannel>test</inboundChannel>
      <!-- deleted timestamp for example -->
      <requestedDocuments>
        <ns2:document xmlns:ns2="some.other.url.02">orderForm</ns2:document>
      </requestedDocuments>
    </orderControl>
  </orderEntry>
</order>

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

Мой XSLT выглядит примерно так:

<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="some.url.02"
  xmlns:ns2="some.other.url.02"
  xmlns:ns3="another.one.02"
>
  <xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="yes" indent="yes"/>

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

  <xsl:template match="*">
    <xsl:choose>
      <xsl:when test="name(.) != 'timestamp'">
        <xsl:element name="{node-name(.)}">
          <xsl:apply-templates select="@*|node()"/>
        </xsl:element>
      </xsl:when>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="@*">
    <xsl:attribute name="{node-name(.)}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>
</xsl:stylesheet>

Может кто-нибудь помочь, пожалуйста? Пространства имен хитры: (

П.С .: Кто бы ни редактировал мою запись: Спасибо:)

Ответы [ 4 ]

2 голосов
/ 22 октября 2009

Вы можете установить пространство имен для выходного элемента с атрибутом namespace:

<xsl:element name="{node-name(.)}" namespace="http://www.bar.org">
  // ...
</xsl:element>

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

Вот ссылка на превосходное учебное пособие по ZVON, в котором есть примеры: http://www.zvon.org/xxl/XSLTreference/Output/xslt_element_namespace.html

Я согласен, что пространства имен хитры. Как вы знаете, префикс семантически не имеет значения, но многие системы позволяют вам выбирать префикс по эстетическим соображениям. Также посмотрите на саксонский (http://saxon.sourceforge.net/)

РЕДАКТИРОВАТЬ Я думаю, вы найдете ответ здесь: Пространство имен корневого тега XSLT вместо пространства имен атрибута элемента

1 голос
/ 22 октября 2009
<xsl:stylesheet
  version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:ns1_src="some.url.01"
  xmlns:ns2_src="some.other.url"
  xmlns:ns3_src="another.one"
  xmlns="some.url.02"
  xmlns:ns2="some.other.url.02"
  xmlns:ns3="another.one.02"
>
  <!-- 
    Note that all the source namespaces got their own new "*_src" prefix. 
    The target namespaces take over the original prefixes. 
    "some.url.02" is the new global namespace.
  -->

  <xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <!-- the identity template to copy everything, unless 
       it has been declared otherwise -->
  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
  </xsl:template>

  <!-- three templates to handle elements -->
  <xsl:template match="ns1_src:*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="node() | @*" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="ns2_src:*">
    <xsl:element name="ns2:{local-name()}">
      <xsl:apply-templates select="node() | @*" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="ns3_src:*">
    <xsl:element name="ns3:{local-name()}">
      <xsl:apply-templates select="node() | @*" />
    </xsl:element>
  </xsl:template>

  <!-- three templates to handle attributes -->
  <xsl:template match="@ns1_src:*">
    <xsl:attribute name="{local-name()}">
      <xsl:value-of select="." />
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="@ns2_src:*">
    <xsl:attribute name="ns2:{local-name()}">
      <xsl:value-of select="." />
    </xsl:attribute>
  </xsl:template>

  <xsl:template match="@ns3_src:*">
    <xsl:attribute name="ns3:{local-name()}">
      <xsl:value-of select="." />
    </xsl:attribute>
  </xsl:template>

  <!-- timestamps will be ignored -->
  <xsl:template match="ns1_src:timestamp" />

</xsl:stylesheet>

Выход:

<order xmlns="some.url.02">
  <orderEntry>
    <orderControl>
      <mandant>test</mandant>
      <businessUnit>test</businessUnit>
      <inboundChannel>test</inboundChannel>
      <requestedDocuments>
        <ns2:document xmlns:ns2="some.other.url.02">orderForm</ns2:document>
      </requestedDocuments>
    </orderControl>
  </orderEntry>
</order>
0 голосов
/ 22 октября 2009

Используете ли вы задачу Ant XSLT для преобразования?

Если ответ «да», вы можете перейти с стандартного движка XSLT, поставляемого с Sun JDK 1.5+. Читайте это .

Также прочитайте эту статью о пространствах имен в XSLT

0 голосов
/ 22 октября 2009
<xsl:template match="a:*">
  <xsl:element name="{local-name()}"
               namespace="http://example.com/B">
    <xsl:copy-of select="@*" />
    <xsl:apply-templates />
  </xsl:element>
</xsl:template>

Он ищет любой элемент в пространстве имен с префиксом a и заменяет его элементом с тем же именем пространства имен http://example.com/B. Все атрибуты копируются «как есть», а затем оцениваются все дочерние элементы.

Добавьте пользовательскую обработку в нужную область или вокруг нее.

...