The basic building block of XSL is the xsl:template tag. It has one principal attribute, match, that takes an XPath query.
As part of the body text of the template tag, you will use xsl:apply-templates, which continues processing nodes further down in the XML tree. It has one attribute, select, which behaves like match.
In the examples below, replace 'node' with the tag you use in your xml. For example, if you have a tag called person:
<person>Guido</person>
Node is 'person'.
Here's a few basic queries:
//node
match, anywhere in the document, tags with the name node
/node
match, just at the root, tags with the name node
/node1//node2
match any tag with the name node2 that is underneath node1, which is at the root
.
select the current node
*
match all nodes at the current level of processing
/*
match any tag at the root
/*[@school='engineering']
match all nodes at the root with an attribute school that is set to equal 'engineering'
/*[name()='seanDavis']
this would be the same as //seanDavis while this example seems pointless look at the next one
/*[count(name()='voijinOklobja')=0]
this would match all tags in the root, unless there are tags with the name voijinOklobja. You should have a corresponding rule for when the count > 0 if you do this.
/person/children//*[count(*)=0]
select all leaf nodes underneath /person/children
/person/property[count(*/*)>0]
select all nodes under /person/property that have children (no guarantees that their children are leaves though)
/person/name[text()='Guido']
select all person tags which have a child tag which contains just 'Guido'.
/person[position()=last()]
select the last person tag in the root
/person[position()<last()]
select all but the last person tag in the root of the document (you might need to literally use
& l t ; [remove the spaces] rather than <)
/person[./property/*/name()='height']
select only people who have a property named height present
Example:
<xsl:template match="">10]">
filthy rich
<xsl:apply-templates/>
</xsl:template>
xsl:for-each
I found that I was processing a lot of lists, and inserting commas and such between list items. Apply-templates doesn't work very well because you can't insert text around each match. So you need to use xsl:for-each. This takes one attribute, select, and works pretty much like apply-templates.
<!-- process all but the last element -->
<xsl:for-each select="*[position()<last()]">
<xsl:apply-templates select="."/> and
</xsl:for-each>
<!-- process the last element -->
<xsl:apply-templates select="*[position()=last()]">
xsl:value-of
When you are inside a template, you may want to print a value using the same XPath that you use to do matching and selections. Just use the xsl:value-of tag
xsl:value-of select="..."
name() prints out the name of the node inside the <> in your XML
@attributename prints an attribute
text() prints the text inside the braces
variables prefixed by $
xsl:variable
Sometimes you need variables. Here's how to create one, set its value, then display it:
<xsl:variable
name="hag"
select="name()"/>
<xsl:value-of select="$hag"/>
xsl:call-template
You can call a template from another template, so long as the template you are calling also has a unique name attribute. The name can't contain variables, etc (so this is not so useful for inheritance):
<xsl:call-template name="blah"/>
xsl:template and xsl:next-match and priorities
I needed to use inheritance right away. Unfortunately with XSL 1.0 and MSXML 3, you can't. But Saxon supports XSL 2.0, which contains next-match. What this does is that you can have multiple templates that match the same nodes. Set a priority attribute for each (lower numbers have a lower priority) and put xsl:next-match in the higher level priorities, and they will be evaluated in order. For example...
<xsl:template match="/*" priority="1001">
You have created an animal named <xsl:value-of select="name()">
<xsl:next-match/>
</xsl:template>
<xsl:template match="/dog" priority="1">
Woof woof
</xsl:template>
Will say 'You have created an animal named ...' for each node in the root. If you happen to have a node named 'dog', it will also say 'Woof woof' after the above text.
No comments:
Post a Comment