tags:

views:

53

answers:

2

can i use xsl or another thing similar to change this format

  <rr n="Address">
  <tt>
  <j n="currentAddress">0</j> 
  <j n="city">city</j> 
  </tt>
  </rr>

to this :-

  <Address>
  <tt>
  <currentAddress>0</currentAddress> 
  <city>city</city> 
  </tt>
  <Address>

notice that i want the attribute value to become the element and remove the attribute if possible please post method.

thank you

+1  A: 

Yes XSL can be used :).

Here is XSL :

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
    <xsl:output omit-xml-declaration="yes" indent="yes" />


    <xsl:template match="/">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="*">
        <xsl:choose>
            <xsl:when test="@n">
                <xsl:variable name="eleName">
                    <xsl:value-of select="@n" />
                </xsl:variable>
                <xsl:element name="{$eleName}">
                    <xsl:value-of select="text()" />
                    <xsl:apply-templates select="*" />
                </xsl:element>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="*" />
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>

    </xsl:template>

</xsl:stylesheet>
YoK
+2  A: 

This stylesheet would also work:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
<xsl:output indent="yes" />

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

<!--specialized template for elements with an "n" attribute-->
<xsl:template match="*[@n]">
    <xsl:element name="{@n}">
        <xsl:apply-templates select="node()"/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

The first template in an identity template which matches on @* (which means any attribute) and node() (which means any element, text node, processing-instruction, or comment). The default behavior is to copy the matched item, and then apply-templates to any of it's attributes or child nodes.

If no other templates were declared in the stylesheet, then that identity template would match for everything and the XSLT would simply make a copy of the XML document.

The second template matches on *[@n], which is any element that has an "n" attribute. * is a wildcard match for any element. The square brackets are a predicate filter, which act kind of like an SQL WHERE clause. Any conditions specified in the predicate must be true in order for the template match to select whatever is being fitlered. The predicate filter evaluates from the context of the matched item, so assuming that you are "standing" on an element, does it have an @n? If so, then this template matches.

The second template has a more specific match criteria than the first "identity" template, so it "wins" and will match for elements that have an @n.

The logic for the second template is to create an element with the name of the value of the @n and then apply-templates for any of the child node() (which includes both text() and elements, but does not include attributes).

Mads Hansen
thank you very much work perfect could you please explain match i would like to understand the answer
new
I've updated the answer with a brief explanation.
Mads Hansen
+1 for a good solution and explanation.
Dimitre Novatchev
@Mads Hansen: +1 Good answer. Do note that `<xsl:apply-templates select="node()"/>` is the same as `<xsl:apply-templates/>`
Alejandro