IManole
IManole

Reputation: 11

XSL Transformation with namespaces

I have this xml file:

<doc xmlns:my="http://example.com" xmlns:my2="test" my:id="AAA">
  <Test>This is the first paragraph.</Test>
  <TEST>This is the second paragraph.</TEST>
  <my2:TEst>This is the second paragraph.</my2:TEst>
</doc> 

and I want to obtain this format:

<doc my:id="AAA" xmlns:my="http://example.com" xmlns:my2="test">
  <test>This is the first paragraph.</test>
  <test>This is the second paragraph.</test>
  <my2:test>This is the second paragraph.</my2:test>
</doc>

That is: if a have in a node an upper case I want to convert all in lowercase(no matter where and in how many nodes).

with this .xls:

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:my="http://example.com" xmlns:my2="test">

  <xsl:variable name="vUpper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
  <xsl:variable name="vLower" select="'abcdefghijklmnopqrstuvwxyz'"/>

  <xsl:template match="@* | node()">
    <new-doc>
      <xsl:apply-templates/>
    </new-doc>
  </xsl:template>

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

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

  <xsl:template match="*">
  <xsl:element name="{translate(name(.),$vUpper,$vLower)}">
    <xsl:apply-templates select="@* | node()"/>
  </xsl:element>
  </xsl:template>

</xsl:stylesheet>

I got this format:

<doc my:id="AAA" xmlns:my="http://example.com">
  <test>This is the first paragraph.</test>
  <test>This is the second paragraph.</test>
  <my2:test xmlns:my2="test">This is the second paragraph.</my2:test>
</doc>

I do not want to have the namespace expanded in the child nodes. Just the aliases. How can I can I reach this goal?(I'm very new to XSL Transformations)

thank you

Upvotes: 1

Views: 43

Answers (2)

IManole
IManole

Reputation: 11

There is indeed problem if the namespace came in upper case like:

<doc my:id="AAA" xmlns:my="http://example.com" xmlns:MY2="test">
  <test>This is the first paragraph.</test>
  <test>This is the second paragraph.</test>
  <MY2:test>This is the second paragraph.</MY2:test>
 </doc>

the output is:

<doc my:id="AAA" xmlns:my="http://example.com" xmlns:MY2="test">
  <test>This is the first paragraph.</test>
  <test>This is the second paragraph.</test>
  <my2: xmlns:my2="test" test>This is the second paragraph.</my2:test>
</doc>

I'll see I I can find another solution. Thank you for your help.

Upvotes: 0

michael.hor257k
michael.hor257k

Reputation: 117140

The placement of a namespace declaration is insignificant. The result you want is semantically identical to the result you get, and you should not need to care about the lexical difference.

Still, depending on the goodwill of your XSLT processor, you might be able to get the result you want using:

XSLT 1.0

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

<xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
<xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>

<xsl:template match="*">
    <xsl:element name="{translate(name(), $upper, $lower)}" namespace="{namespace-uri()}">
        <xsl:copy-of select="@* | namespace::*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

Note that this is assuming the original namespace prefixes are already in lower-case.

Upvotes: 1

Related Questions