Publishers of technology books, eBooks, and videos for creative people

Home > Articles > Web Design & Development

  • Print
  • + Share This
  • 💬 Discuss

From the author of

Altering Document Structure Based on Input

So far, the templates in this chapter have been fairly rigid skeletons, specifying exactly what should go into the output document in what order. But you can use XSLT elements such as <xsl:element>, <xsl:attribute>, <xsl:text>, and so on to create new nodes on the fly, based on what you find in the input document. I’ll take a look at how this works now.

Creating Attribute Templates

Say that you wanted to convert the text in some elements to attributes in other elements—how could you do it? Attribute values must be quoted in XML, but you can’t just use expressions like these, where I’m taking the values of <NAME>, <MASS>, and <DAY> elements and trying to make them into attribute values:

<xsl:template match="PLANET">
    <PLANET NAME="<xsl:value-of select=’NAME’/>"
        MASS="<xsl:value-of select=’MASS’/>"
        DAY="<xsl:value-of select=’DAY’/>"
    />

This won’t work because you can’t use < inside attribute values, as I have here. Instead, you must use an expression like {NAME}; here’s the proper XSLT:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="PLANETS">
    <HTML>
        <HEAD>
            <TITLE>
                Planets
            </TITLE>
        </HEAD>
        <BODY>
            <xsl:apply-templates select="PLANET"/>
        </BODY>
    </HTML>
</xsl:template>

<xsl:template match="PLANET">
    <PLANET NAME="{NAME}"
        MASS="{MASS}"
        DAY="{DAY}"
    />
</xsl:template>
</xsl:stylesheet>

Here’s the resulting document—note that I’ve been able to convert the values in various elements to attributes:

<HTML>
<HEAD>
<TITLE>
                Planets
            </TITLE>
</HEAD>
<BODY>
<PLANET DAY="58.65" MASS=".0553" NAME="Mercury">
</PLANET>
<PLANET DAY="116.75" MASS=".815" NAME="Venus">
</PLANET>
<PLANET DAY="1" MASS="1" NAME="Earth">
</PLANET>
</BODY>
</HTML>

You can even include multiple expressions in curly braces, like this, where I’m adding the units for mass and day measurements from the UNITS attribute in the original elements:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="PLANETS">
    <HTML>
        <HEAD>
            <TITLE>
                Planets
            </TITLE>
        </HEAD>
        <BODY>
            <xsl:apply-templates select="PLANET"/>
        </BODY>
    </HTML>
</xsl:template>

<xsl:template match="PLANET">
    <PLANET NAME="{NAME}"
        MASS="{MASS} {MASS/@UNITS}"
        DAY="{DAY} {DAY/@UNITS}"
    />
</xsl:template>
</xsl:stylesheet>

Creating New Elements

You can create new elements with the <xsl:element> element. For example, say that I store the name of planets in a NAME attribute instead of a <NAME> element in planets.xml, like this:

<?xml version="1.0"?>
<?xml-stylesheet type="text/xml" href="planets.xsl"?>
<PLANETS>

  <PLANET NAME="Mercury">
      <MASS UNITS="(Earth = 1)">.0553</MASS>
      <DAY UNITS="days">58.65</DAY>
      <RADIUS UNITS="miles">1516</RADIUS>
      <DENSITY UNITS="(Earth = 1)">.983</DENSITY>
      <DISTANCE UNITS="million miles">43.4</DISTANCE><!—At perihelion—>
  </PLANET>
    .
    .
    .

I could create a new element using the name of the planet with <xsl:element>, supplying the name of the new planet with the name attribute, and enclosing a <MASS> element this way:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="PLANETS">
    <HTML>
        <HEAD>
            <TITLE>
                Planets
            </TITLE>
        </HEAD>
        <BODY>
            <xsl:apply-templates select="PLANET"/>
        </BODY>
    </HTML>
</xsl:template>

<xsl:template match="PLANET">
    <xsl:element name="{@NAME}">
        <MASS><xsl:value-of select="MASS"/></MASS>
    </xsl:element>
</xsl:template>
</xsl:stylesheet>

Here is the result, where I’ve created a new <mercury> element:

<HTML>
<HEAD>
<TITLE>
                Planets
            </TITLE>
</HEAD>
<BODY>
<Mercury>
<MASS>.0553</MASS>
</Mercury>
    .
    .
    .

In this way, you can create new elements and name them when the XSLT transformation takes place.

Creating New Attributes

Just as you can create new elements with <xsl:element> and set the element name and content under programmatic control, you can do the same for attributes using the <xsl:attribute> element.

Here’s an example; in this case, I’m creating new <PLANET> elements with attributes corresponding to the various planet names, and values taken from the COLOR attribute in the original <PLANET> elements:

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="PLANETS">
    <HTML>
        <HEAD>
            <TITLE>
                Planets
            </TITLE>
        </HEAD>
        <BODY>
            <xsl:apply-templates select="PLANET"/>
        </BODY>
    </HTML>
</xsl:template>

<xsl:template match="PLANET">
    <PLANET>
        <xsl:attribute name="{NAME}">
            <xsl:value-of select="@COLOR"/>
        </xsl:attribute>
    </PLANET>
</xsl:template>
</xsl:stylesheet>

Here are the results; as you can see, I’ve created new attributes on the fly, using the names of the planets:

<HTML>
<HEAD>
<TITLE>
                Planets
            </TITLE>
</HEAD>
<BODY>
<PLANET Mercury="RED">
</PLANET>
<PLANET Venus="WHITE">
</PLANET>
<PLANET Earth="BLUE">
</PLANET>
</BODY>
</HTML>
  • + Share This
  • 🔖 Save To Your Account
Inside XML

From the author of

Inside XML

Discussions

comments powered by Disqus