Изменение пространства имен для файла XML в XSL Translation

Итак, у меня есть входной файл, который использует пространство имен моей компании в пространстве имен по умолчанию (xmlns="companyURL"), но я хочу, чтобы мой выходной файл использовал что-то другое, чем пространство имен по умолчанию (xmlns:cmp="companyURL"). Итак, я создаю свой файл, используя пространство имен cmp, но затем я хочу скопировать некоторые внутренние элементы:

<xsl:element name="cmp:container">
  <xsl:for-each select="foo">
    <xsl:copy-of select="." />
  </xsl:for-each>
</xsl:element>

К сожалению, это определяет пространство имен по умолчанию для каждого из этих внутренних элементов, что делает файл невероятно многословным и уродливым. Упрощенный пример:

Источник:

<foo xmlns="companyURL">
  <num1>asdf</num1>
  <num2>ghjkl</num2>
</foo>

Превращается в:

<cmp:container xmlns:cmp="companyURL">
  <num1 xmlns="companyURL">asdf</num1>
  <num2 xmlns="companyURL">ghjkl</num2>
</cmp:container>

Конечно, companyURL большое, длинное и уродливое, и оно одинаково в обоих местах, поэтому я бы предпочел, чтобы вышеприведенный результат был следующим:

<cmp:container xmlns:cmp="companyURL">
  <cmp:num1>asdf</cmp:num1>
  <cmp:num2>ghjkl</cmp:num2>
</cmp:container>

Есть ли простой способ сделать это или мне следует преобразовать все в пространстве имен cmp в пространство имен по умолчанию? Я бы предпочел использовать явное именование пространства имен, если это возможно, это помогает понять XSLT по моему опыту.


person adam_0    schedule 12.08.2010    source источник
comment
Хороший вопрос (+1). Смотрите мой ответ для короткого и простого решения, :)   -  person Dimitre Novatchev    schedule 12.08.2010
comment
хочу, чтобы в моем выходном файле использовалось пространство имен, отличное от пространства имен по умолчанию ›› следуя вашему примеру, изменение префикса (или с префикса по умолчанию на префикс) не означает изменение пространства имен. Элементы, с точки зрения XML+NS, останутся одинаковыми (localname + namespace не меняются), даже если префикс отличается.   -  person Abel    schedule 12.08.2010
comment
Я имел в виду видимый идентификатор перед именем тега.   -  person adam_0    schedule 12.08.2010


Ответы (1)


Это преобразование:

 <xsl:template match="*">
     <xsl:element name="cmp:{name()}" namespace="CompanyURL">
       <xsl:copy-of select="@*"/>
       <xsl:apply-templates/>
     </xsl:element>
 </xsl:template>
 <xsl:template match="/*">
     <cmp:container xmlns:cmp="CompanyURL">
       <xsl:copy-of select="@*"/>
       <xsl:apply-templates/>
     </cmp:container>
 </xsl:template>
</xsl:stylesheet>

при выполнении с предоставленным XML-документом:

<foo xmlns="companyURL">
  <num1>asdf</num1>
  <num2>ghjkl</num2>
</foo>

выдает желаемый правильный результат:

<cmp:container xmlns:cmp="CompanyURL">
   <cmp:num1>asdf</cmp:num1>
   <cmp:num2>ghjkl</cmp:num2>
</cmp:container>
person Dimitre Novatchev    schedule 12.08.2010
comment
Почему у вас есть <xsl:copy-of select="@*"/> в вашем XSLT? - person adam_0; 12.08.2010
comment
@adam_0: это копирует все атрибуты элемента. В вашем конкретном примере нет атрибутов, но если мы хотим использовать этот код в качестве общего преобразователя, он должен уметь корректно конвертировать все документы, в том числе и те, в которых есть элементы с атрибутами. - person Dimitre Novatchev; 12.08.2010
comment
Моя XML-схема указывает, что атрибутов не будет, поэтому я предполагаю, что можно оставить эту строку? - person adam_0; 12.08.2010
comment
Если вы на 100% уверены, что можете удалить его, но если оставить, это ничего не повредит — просто никакие атрибуты не будут скопированы. Всегда лучше иметь более общий код. Представьте, что завтра произойдет изменение схемы и появятся атрибуты. Затем вам нужно будет добавить копирование атрибутов. Если вы с самого начала использовали более общий код, это изменение схемы никак не повлияет на вас. - person Dimitre Novatchev; 12.08.2010
comment
Спасибо за вашу помощь и мощные, краткие ответы. +1 - person adam_0; 12.08.2010
comment
Дополнение, о котором я только что подумал: могу ли я заставить это работать для любого префикса пространства имен, изменив верхнюю строку шаблона <xsl:element name="cmp:{name()}" namespace="CompanyURL"> на <xsl:element name="cmp:{local-name()}" namespace="CompanyURL"> (фактически обрезав любой префикс пространства имен и поставив свой собственный)? - person adam_0; 12.08.2010
comment
@adam_0: Да, это способ переименования префикса. - person Dimitre Novatchev; 12.08.2010