Промяна на пространството на имената за 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