0

I need to convert all my attributes in the xml to elements with some conditions. Say for example some attributes should be prefixed with the "Value" to it. I achieved this far. Along with this I need to change my namespace also. I couldn't achieve that.

XML

<Template xmlns="styling/1.0.0" Name="TemplateFromDictionary">

  <Style Name="Default">
    <Fill Color=""/>
    <Stroke Color="0000FF" LineStyle="Single" Width="1"/>
    <Symbol Color="FFFFFF" Name="default.png" ScaleX="100" ScaleY="100" ScaleMode="Drawing"/>
  </Style>

  <Style Name="Parcel">
    <Fill Color="48F5F5F5"/>
    <Stroke Color="C0C0C0" LineStyle="Single" Width="1"/>
    <Symbol Color="FFFFFF" Name="default.png" ScaleX="100" ScaleY="100" ScaleMode="Drawing"/>
  </Style>

</Template>

XSLT

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                exclude-result-prefixes="msxsl"
                xmlns:s="styling/1.0.0"
                xmlns="styling/1.0.0">

  <xsl:output method="xml" indent="yes"/>

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

  <xsl:template match="s:Style|s:Template">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="@*">
    <xsl:variable name="name">
      <xsl:apply-templates select="." mode="name"/>
    </xsl:variable>
    <xsl:element name="{$name}">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="@Color|@Width|@ScaleX|@ScaleY|@LeftIndent|@RightIndent|@FirstLineIndent|@SpaceBefore|@SpaceAfter|@Size" mode="name">
    <xsl:value-of select="concat(name(), 'Value')"/>
  </xsl:template>

  <xsl:template match="@*" mode="name">
    <xsl:value-of select="name()"/>
  </xsl:template>

</xsl:stylesheet>

OUTPUT

<?xml version="1.0" encoding="utf-8"?>
<Template Name="TemplateFromDictionary" xmlns="styling/1.0.0">

  <Style Name="Default">
    <Fill>
      <ColorValue></ColorValue>
    </Fill>
    <Stroke>
      <ColorValue>0000FF</ColorValue>
      <LineStyle>Single</LineStyle>
      <WidthValue>1</WidthValue>
    </Stroke>
    <Symbol>
      <ColorValue>FFFFFF</ColorValue>
      <Name>default.png</Name>
      <ScaleXValue>100</ScaleXValue>
      <ScaleYValue>100</ScaleYValue>
      <ScaleMode>Drawing</ScaleMode>
    </Symbol>
  </Style>

  <Style Name="Parcel">
    <Fill>
      <ColorValue>48F5F5F5</ColorValue>
    </Fill>
    <Stroke>
      <ColorValue>C0C0C0</ColorValue>
      <LineStyle>Single</LineStyle>
      <WidthValue>1</WidthValue>
    </Stroke>
    <Symbol>
      <ColorValue>FFFFFF</ColorValue>
      <Name>default.png</Name>
      <ScaleXValue>100</ScaleXValue>
      <ScaleYValue>100</ScaleYValue>
      <ScaleMode>Drawing</ScaleMode>
    </Symbol>
  </Style>

</Template>

In output instead of this

<Template Name="TemplateFromDictionary" xmlns="styling/1.0.0">

I need this

<Template Name="TemplateFromDictionary" xmlns="styling/2.0.0">

I tried by changing the namespace in xslt to xmlns="styling/2.0.0" But this is giving the results like

<Fill><ColorValue xmlns="styling/2.0.0"></ColorValue></Fill>

The namespace is embedded into all elements and the Template element looks the same

<Template Name="TemplateFromDictionary" xmlns="styling/1.0.0">

I need the output exactly same as the output mentioned above only that namespace in Template element needs to be changed.

I am transforming this with C#.

Please help me on this.

2 Answers 2

1

To change the namespace of all elements you can reconstruct them with xsl:element using a namespace attribute. So the following code changes two templates and adds a general "use-new-namespace" template:

<!-- use-new-namespace template for all s:* elements -->
<xsl:template match="s:*">   
    <xsl:element name="{local-name()}" namespace="styling/2.0.0">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
</xsl:template>  

<!-- modified templates for new namespace -->
<xsl:template match="s:Style|s:Template">
    <xsl:element name="{local-name()}" namespace="styling/2.0.0">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()"/>
    </xsl:element>
</xsl:template>  

<xsl:template match="@*">
    <xsl:variable name="name">
      <xsl:apply-templates select="." mode="name"/>
    </xsl:variable>
    <xsl:element name="{$name}" namespace="styling/2.0.0">
      <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

So the whole XSLT file is:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                exclude-result-prefixes="msxsl"
                xmlns:s="styling/1.0.0"
                xmlns:t="styling/2.0.0">

  <xsl:output method="xml" indent="yes"/>

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

  <!-- use-new-namespace template for s:* elements -->
  <xsl:template match="s:*">   
    <xsl:element name="{local-name()}" namespace="styling/2.0.0">
      <xsl:apply-templates select="@* | node()"/>
    </xsl:element>
  </xsl:template>  

  <!-- modified templates for new namespace -->
  <xsl:template match="s:Style|s:Template">
    <xsl:element name="{local-name()}" namespace="styling/2.0.0">
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()"/>
    </xsl:element>
  </xsl:template>  

  <xsl:template match="@*">
    <xsl:variable name="name">
      <xsl:apply-templates select="." mode="name"/>
    </xsl:variable>
    <xsl:element name="{$name}" namespace="styling/2.0.0">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="@Color|@Width|@ScaleX|@ScaleY|@LeftIndent|@RightIndent|@FirstLineIndent|@SpaceBefore|@SpaceAfter|@Size" mode="name">
    <xsl:value-of select="concat(name(), 'Value')"/>
  </xsl:template>

  <xsl:template match="@*" mode="name">
    <xsl:value-of select="name()"/>
  </xsl:template>

</xsl:stylesheet>
Sign up to request clarification or add additional context in comments.

4 Comments

I am so sorry I couldn't understand. Could you please elaborate a bit?
In short, add the first template above and change the other two in your XSLT. Then every element will get the new namespace.
I have now one more problem in this. This is a new enhancement I need to do. Actually while writing the output for symbols <Name>default.png</Name> the name attribute has to be prefixed with C:\ or C:\dwg\ based on the content in the Name attribute contains 'png' or 'dwg'. I tried putting the condition in here inside this <xsl:template match="@*">. But I couldn't get this working. Could you please help me on this ?
@shansfk: I guess this qualifies as a whole new question. I can't tell from the comment what you expect to be changed...maybe a case for xsl:choose... A new questions with a good minimal reproducible example will surely help with that.
0

One way to achieve your goal is to rewrite the Template element with the new namespace. For example : add the following template to your xslt:

<xsl:template match="s:Style">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>

<xsl:template match="s:Template" xmlns:ns2="styling/2.0.0">
  <ns2:Template>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates select="node()"/>
  </ns2:Template>
</xsl:template>

and remove the old s:Style|s:Template matching template

to be more clear:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:msxsl="urn:schemas-microsoft-com:xslt"
                exclude-result-prefixes="msxsl"
                xmlns:s="styling/1.0.0"
                xmlns="styling/1.0.0">

  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
<!--    
  <xsl:template match="s:Style|s:Template">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>
-->    
<xsl:template match="s:Style">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:apply-templates select="node()"/>
    </xsl:copy>
  </xsl:template>

<xsl:template match="s:Template" xmlns:ns2="styling/2.0.0">
  <ns2:Template>
    <xsl:copy-of select="@*"/>
    <xsl:apply-templates select="node()"/>
  </ns2:Template>
</xsl:template>

  <xsl:template match="@*">
    <xsl:variable name="name">
      <xsl:apply-templates select="." mode="name"/>
    </xsl:variable>
    <xsl:element name="{$name}">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="@Color|@Width|@ScaleX|@ScaleY|@LeftIndent|@RightIndent|@FirstLineIndent|@SpaceBefore|@SpaceAfter|@Size" mode="name">
    <xsl:value-of select="concat(name(), 'Value')"/>
  </xsl:template>

  <xsl:template match="@*" mode="name">
    <xsl:value-of select="name()"/>
  </xsl:template>

</xsl:stylesheet>

1 Comment

Don't you think OP might want the new namespace applied to all elements, and the old namespace essentially discarded?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.