Как я могу динамически установить объявление пространства имен по умолчанию для выходного XML-файла XSLT-преобразования? - PullRequest
4 голосов
/ 12 марта 2010

Я могу сделать это, но не для пространства имен по умолчанию, используя <xsl:namespace>. Если я пытаюсь сделать это для пространства имен по умолчанию:

<xsl:namespace name="" select"myUri"/>

это никогда не работает. Он требует, чтобы я явно определил пространство имен элемента, чтобы можно было использовать вышеуказанное объявление нулевого префикса.
Причина, по которой я этого хочу, заключается в том, что у меня есть задача преобразовать входной XML-файл в другой выходной XML. Выходной XML имеет много элементов, и я не хочу явно задавать пространство имен для каждого элемента. Вот почему я хочу установить значение по умолчанию и больше никогда не беспокоиться. Но значение по умолчанию должно быть вычислено из некоторых данных в исходном XML. Он не изменяется в течение всего преобразования, но зависит от входных данных XML. Любое решение?

РЕДАКТИРОВАТЬ 1: Для поддержки:

  1. Я хочу динамически создать пространство имен и установить его в качестве пространства имен по умолчанию для выходного XML-документа. URI пространства имен получен из некоторых данных во входном XML.
  2. Если я использую <xsl:namespace> в своем корневом элементе вывода, я не могу создать для него пространство имен по умолчанию, только префиксное. И даже с префиксом он не распространяется на детей.

РЕДАКТИРОВАТЬ 2: dkackman предложил:

<xsl:template match="root">
  <xsl:param name ="ns">my-computed-namespace</xsl:param>
  <xsl:element name="newRoot" namespace="{$ns}"/>
</xsl:template>

Это почти решает проблему. К сожалению, детям вводится "" (пустое) пространство имен преобразователем. Вот что я получу, если добавлю дочерний элемент:

<newRoot xmlns="my-computed-namespace"> 
    <child xmlns=""> ... 
    </child> 
 </newRoot>

Почему трансформатор помещает это xmlns="" в детей? Если я смогу предотвратить это, я найду свое решение.

Ответы [ 3 ]

7 голосов
/ 12 марта 2010

В дополнение к @Tomalak, который предоставил точный ответ, обратите внимание, что <xsl:namespace> не предназначен для создания объявления пространства имен, которое будет использоваться процессором XSLT, как правило со всеми элементами или атрибутами.

Цель <xsl:namespace> - создать определенный узел пространства имен . Этот узел имеет только ограниченную область действия: текущий элемент или атрибут и все дочерние элементы текущего узла, если они не переназначают префикс другому namespace-uri.

Использование <xsl:namespace> необходимо, только если мы хотим динамически создать пространство имен для пространства имен-uri, которое должно генерироваться динамически (статически не было известно в начале преобразования). Такие случаи крайне редки.

Во всех случаях, когда требуемый namspace-uri известен статически, просто объявите это пространство имен с подходящим уровнем видимости (обычно в инструкции <xsl:stylesheet>), а затем просто используйте связанный префикс в любом месте это пространство имен должно быть использовано.

UPDATE: Я только что подтвердил в диалоге со специалистами на другом форуме, что это невозможно сделать с <xsl:namespace>. Он добавляет узел пространства имен без имени к текущему элементу, но буквальные результирующие элементы копируются 1: 1 и остаются в их (нет) пространстве имен.

Вот как объясняет это доктор Майкл Кей, редактор W3C WG по XSLT:

" Вам необходимо создать элементы и атрибуты с правильным расширенным именем в время, когда вы их создаете. Если это означает использование xsl:element, пусть будет так. xsl:namespace может использоваться только для создания дополнительных узлов пространства имен для этих которые создаются автоматически для префиксов / Uris, используемых в элементе и имена атрибутов; его нельзя использовать для изменения имени элемента или Атрибутивный узел. Как всегда, чтобы понять это, вам нужно понять модель данных для Пространства имен. Имя элемента / атрибута является тройкой, содержащей (prefix, uri, localname). Узел пространства имен - это пара (prefix, uri). Есть последовательность правило, что если существует имя элемента или атрибута, содержащее prefix=P uri=U тогда должен быть узел пространства имен (P, U). Процесс исправления пространства имен гарантирует, что этот узел пространства имен создается автоматически при создании элемент или атрибут. xsl:namespace есть, чтобы позволить вам создать дополнительные узлы пространства имен, как правило, для пространств имен, используемых в значении QName содержание ».

Если такой результат необходим, решение состоит в том, чтобы использовать второй проход и преобразовать любой элемент, принадлежащий «пространству имен», в желаемое новое пространство имен.

Это преобразование для использования во втором проходе (два прохода можно объединить в одну таблицу стилей / преобразование):

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

  <xsl:variable name="vUrl" select="'my:Url'"/>

 <xsl:template match="*[namespace-uri()='']">
   <xsl:element name="{name()}" namespace="{$vUrl}">
     <xsl:copy-of select="@*"/>
     <xsl:apply-templates/>
   </xsl:element>

 </xsl:template>
</xsl:stylesheet>

Когда применяется указанное преобразование к следующему образцу (pass-1-result) XML-документа:

<a>
  <b>
    <c/>
  </b>
</a>

Получен желаемый результат :

<a xmlns="my:Url">
    <b>
        <c/>
    </b>
</a>
1 голос
/ 12 марта 2010

Простой:

<xsl:stylesheet
 version="1.0"
 xmlns:xsl="..."
 xmlns="default output namespace for unprefixed elements"
>
  <!-- ... -->
</xsl:stylesheet>
0 голосов
/ 12 марта 2010

Попробуйте это:

<xsl:template match="root">
  <xsl:param name ="ns">my-computed-namespace</xsl:param>
  <xsl:element name="newRoot" namespace="{$ns}"/>
</xsl:template>

Тогда вы можете назвать это так:

    <xsl:apply-templates select="root">
      <xsl:with-param name="ns" select="computationXPath"/>
    </xsl:apply-templates>

EDIT Или с variable вместо param:

  <xsl:variable name ="ns">my-computed-namespace</xsl:variable>
  <xsl:template match="root">
    <xsl:element name="newRoot" namespace="{$ns}">
       <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

(не нужно вызывать шаблоны with-param)

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