web analytics

Creating New Elements with Attributes in XSLT

Options

codeling 1595 - 6639
@2017-09-12 11:49:53

When outputting XML or HTML, you will need to output element and attributes. A XSLT style sheet can instruct an XSLT processing program to output element and attributes using literal result elements. However, it's not always possible to know the names of the new elements you want to create. Whether you're converting an element to a new attribute, an attribute to a new element, or supplying either with a function's return value or a hardcoded string, you nedd a way to create both elements and attributes dynamically to your output.

<xsl:element>: Creating New Elements at Runtime

The <xsl:element> element is very useful if you need to determine a new element's name at runtime. Here are the three attributes of this element:

  • name (mandatory): Name of the element you want to create. Set to an attribute value template that returns a QName.

  • namespace (optional): The namespace uniform resource identifier (URI) of the new element. Set to an attribute value template returning a URI.

  • use-attribute-sets (optional): Specifies the attribute sets containing the attributes for this element. Set to a whitespace-separated list of QNames.

<xsl:attribute>: Adding New Attributes at Runtime

The xsl:attribute element is used to add an attribute value to an xsl:element element or general formatting element, or to an element created using xsl:copy. The attribute must be output immediately after the element, with no intervening character data. The name of the attribute is indicated by the name attribute and the value by the content of the xsl:attribute element.

There are two main uses for the xsl:attribute element:

  • It is the only way to set attributes on an element generated dynamically using xsl:element
  • It allows attributes of a literal result element to be calculated using xsl:value-of.

The xsl:attribute must be output immediately after the relevant element is generated: there must be no intervening character data (other than white space which is ignored). SAXON outputs the closing ">" of the element start tag as soon as something other than an attribute is written to the output stream, and rejects an attempt to output an attribute if there is no currently-open start tag. Any special characters within the attribute value will automatically be escaped (for example, "<" will be output as "&lt;")

If two attributes are output with the same name, the second one takes precedence.

Example

File: Data.xml

<?xml version="1.0"?>
<?xml-stylesheet href="Transform.xslt" type="text/xsl"?>
<message>Message.</message>


File: Transform.xslt

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

  <xsl:template match="/">
    <xsl:element name="paragraph">
      <xsl:attribute name="priority">medium</xsl:attribute>
      <xsl:attribute name="date">2003-09-23</xsl:attribute>
      <xsl:attribute name="doc:style"
        namespace="http://www.java2s.com/documents">classic</xsl:attribute>       <xsl:apply-templates />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>


Output:

<?xml version="1.0" encoding="UTF-8"?>
<paragraph xmlns:doc="http://www.java2s.com/documents" priority="medium" date="2003-09-23" doc:style="classic">Message.</paragraph>

@2017-09-12 11:53:48

xsl:attribute-set

The xsl:attribute-set element is used to declare a named collection of attributes, which will often be used together to define an output style. It is declared at the top level (subordinate to xsl:stylesheet).

An attribute-set contains a collection of xsl:attribute elements.

The attributes in an attribute-set can be used in several ways:

  • They can be added to a literal result element by specifying xsl:use-attribute-sets in the list of attributes for the element. The value is a space-separated list of attribute-set names. Attributes specified explicitly on the literal result element, or added using xsl:attribute, override any that are specified in the attribute-set definition.
  • They can be added to an element created using xsl:element, by specifying use-attribute-sets in the list of attributes for the xsl:element element. The value is a space-separated list of attribute-set names. Attributes specified explicitly on the literal result element, or added using xsl:attribute, override any that are specified in the attribute-set definition.
  • One attribute set can be based on another by specifying use-attribute-sets in the list of attributes for the xsl:attribute-set element. Again, attributes defined explicitly in the attribute set override any that are included implicitly from another attribute set.

Attribute sets named in the xsl:use-attribute-sets or use-attribute-sets attribute are applied in the order given: if the same attribute is generated more than once, the later value always takes precedence.

If you need to re-use a group of attributes in multiple elements of your output (for example, formatting instructions that apply to several HTML element types upon output), you can store them in an xsl:attribute-set element and then reference the collection with the use-attribute-sets attribute of xsl:element.

For example, the following shows a group of xsl:attribute elements in an xsl:attribute-set element named "widgetAttrs" and an xsl:element element that incorporates those attributes with a value of "widgetAttrs" for its use-attribute-sets attribute. Note how this attribute name is in the plural; the value can list more than one attribute set as long as spaces separate the names and all the names represent existing xsl:attribute-set elements.

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

<xsl:attribute-set name="widgetAttrs">

  <xsl:attribute name="status">done</xsl:attribute>

  <xsl:attribute name="hue"><xsl:value-of select="@color"/></xsl:attribute>

  <xsl:attribute name="number"><xsl:value-of select="amount"/></xsl:attribute>

  <xsl:attribute name="pos"><xsl:value-of select="position() + 6"/></xsl:attribute>

</xsl:attribute-set>


<xsl:template match="thnad">

 <xsl:element name="widget" use-attribute-sets="widgetAttrs">

  <xsl:attribute name="prodmgr">BD</xsl:attribute>

   <xsl:apply-templates/>

 </xsl:element>

</xsl:template>

</xsl:stylesheet>
@2017-09-12 14:04:46

Sometime you don’t have to use xsl:element or xsl:attribute

You can use xsl:element and xsl:attribute, but it leads to very bloated code.

Here are a few examples of what you can do instead. In each example we will just assume we are working with some XML that represents some kind of product (it is not important what this structure is for this discussion).

Use the element name itself rather than xsl:element

Instead of

 
 
<xsl:element name="p">
  <xsl:value-of select="$product/name" />
</xsl:element>

This is a lot cleaner to read:

 
 
 
<p>
  <xsl:value-of select="$product/name" />
</p>

or:

 
<p><xsl:value-of select="$product/name" /></p>

Use the { } shorthand for writing values inside of attributes

Using xsl:value-of for many attributes can get verbose very quickly. There is more code to read. So the code just looks uglier and more bloated. For attributes only then, with most XSLT parsers, you can use the shorthand { as a replacement for <xsl:value-of select=” and } as a replacement for ” />.

In between { and } you just put in your normal select expression.

So, instead of

 
 
 
 
 
 
<h3>
  <xsl:attribute name="class">
    <xsl:value-of select="$product/@type" /></xsl:value-of>
  </xsl:attribute>
  <xsl:value-of select="$product/name" />
</h3>

This is a lot cleaner to read:

 
 
<h3 class="{$product/name}">
  <xsl:value-of select="$product/name" />
</h3>

Or, instead of

 
 
 
 
 
 
<xsl:element name="img">
  <xsl:attribute name="src" select="$product/image/@src" />
  <xsl:attribute name="width" select="$product/image/@width" />
  <xsl:attribute name="height" select="$product/image/@height" />
  <xsl:attribute name="alt" select="$product/image" />
  <xsl:attribute name="class" select="$product/@type" />
</xsl:element>

This is a lot cleaner to read:

 
 
 
 
 
 
 
<img
  src="{$product/image/@src}"
  width="{$product/image/@width}"
  height="{$product/image/@height}"
  alt="{$product/image}"
  class="{$product/@type}"
/>

The above is only put onto multiple lines for this web page. In a proper editor sometimes a one-liner is even easier to read:

 
<img src="{$product/image/@src}" width="{$product/image/@width}" height="{$product/image/@height}" alt="{$product/image}" class="{$product/@type}" />

The above is also looking a lot like some templating languages now, and you might see why I am wondering why there are so many proprietary ones people have to learn, when XSLT is an open, widely supported, standard with transferable skills!

The above also doesn’t show how clean the code would really be, because someone using xsl:attribute is likely to use xsl:element as well, so really we should compare the legibility of this:

 
 
 
 
 
 
<xsl:element name="h3">
  <xsl:attribute name="class">
    <xsl:value-of select="$product/@type" /></xsl:value-of>
  </xsl:attribute>
  <xsl:value-of select="$product/name" />
</xsl:element>

… versus this:

 
 
 
<h3 class="{$product/name}">
  <xsl:value-of select="$product/name" />
</h3>

Comments

You must Sign In to comment on this topic.


© 2024 Digcode.com