tags:

views:

877

answers:

5

Hi, I have an XML program in the following structure

<Part>
     <ID>1</ID>
     <Density>3</Density>
     <Parameter>
           <Element>Alloy</Element>
     </Parameter>
</Part>

I want to create an XSL which tranforms this XML in such a way that

ID 1
Density 3
Element Alloy

How I can do that?? Somebody can help me with this...

+2  A: 

You don't specify your desired output type but I'm gonna guess HTML, not that it matters the same principles can be used. I'm also going to guess that the Parameter element may contain a variety of elements with different tag names.

Here then is the transform:-

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
<xsl:output method="html" />

    <xsl:template match="Part">
        <html>
            <div>
                <xsl:text>ID </xsl:text>
                <xsl:value-of select="ID" />
            </div>
            <div>
                <xsl:text>Density </xsl:text>
                <xsl:value-of select="Density" />
            </div>
            <xsl:for-each select="Parameter/*">
                <div>
                    <xsl:value-of select="name()" />
                    <xsl:text> </xsl:text>
                    <xsl:value-of select="." />
                </div>
            </xsl:for-each>
        </html>
    </xsl:template>

</xsl:stylesheet>
AnthonyWJones
+1  A: 

You need to look at the name() function.

<xsl:value-of select="name()"/>
johnwards
+1  A: 

This sample renders the name and text content of those elements with no child elements.

The output has the following features:

  • uses local-name() to avoid outputting namespace prefixes, eg for <xsl:text/> this is "text"
  • uses normalize-space() to strip leading & trailing whitespace, and to compact sequences of internal whitespace
  • xsl:strip-space to ignore whitespace only text node in the input
  • CRLF line ending
  • output method is text

Sample code:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

    <xsl:output method="text" />
    <xsl:strip-space elements="*" />

    <xsl:template match="*[not(*)]">
        <xsl:value-of select="local-name()" />
        <xsl:text> </xsl:text>
        <xsl:value-of select="normalize-space(.)" />
        <xsl:text>&#10;&#13;</xsl:text>
    </xsl:template>

</xsl:stylesheet>
Lachlan Roche
`0=count(*)` is equivalent to `not(*)`. It's probably simpler to just do `<xsl:template match="*[not(*)]">...` and `<xsl:template match="*"><xsl:apply-templates/></xsl:template>` as separate templates.
Eamon Nerbonne
+1  A: 

As an alternative to Lachlan's code, you could also try

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
<xsl:output method="text" />

<xsl:template match="text()">
  <xsl:if test="normalize-space(.)">
    <xsl:value-of select="local-name(parent::*)" />
    <xsl:text> </xsl:text>
    <xsl:value-of select="normalize-space(.)" />
    <xsl:text>
</xsl:text>
  </xsl:if>
</xsl:template>

</xsl:stylesheet>
Christopher Creutzig
Why a `for-each` for parent? There is only one parent for a given node. `parent` axis is not a function. You could eliminate the `for-each` and use `<xsl:value-of select="local-name(parent::*)"/>`
Mads Hansen
@Mads: Right, sorry. Fixed.
Christopher Creutzig
+2  A: 

A shorter transform, illustrating a few handy techniques for this kind of thing:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;
<xsl:output method="text" />
<xsl:strip-space elements="*"/>    
<xsl:variable name="newline"><xsl:text>
</xsl:text></xsl:variable>

<xsl:template match="text()">
  <xsl:value-of select="concat(local-name(..),' ',normalize-space(.),$newline)"/>
</xsl:template>

</xsl:stylesheet>
  • strip-space says to ignore all white-space only nodes.
  • You can give parameters to functions like local-name.
  • When generating text output, a variable like $newline is often handy.

Optionally, adding the following transform ignores all non-leaf text nodes:

<xsl:transform match="*[*]"><xsl:apply-templates/></xsl:template>
Eamon Nerbonne