Part 2 of Step Patterns: Node Tests

Part 2 of Step Patterns: Node Tests

The second part of a step pattern is made up of node tests. You can use names of nodes as node tests, or the wild card * to select element nodes as well as node types. For example, the expression child::*/child:: NAME selects all <NAME> elements that are grandchildren of the context node.

In addition to node names and the wild card character, you also can use the following node tests:

  • The comment() node test selects comment nodes.

  • The node() node test selects any type of node.

  • The processing-instruction() node test selects a processing instruction node. You can specify the name of the processing instruction to select in the parentheses.

  • The text() node test selects a text node.

The following sections examine these node tests and provide examples to help you understand how theyre used.

Matching Comments

You can match the text of comments with the pattern comment() . You shouldnt store data that should go into the output document in comments in the input document, of course. However, you might want to convert comments from the <!-- comment --> form into something another markup language might use, such as a <COMMENT> element.

In the following example, I will extract comments from planet.xml and include them in the resulting output.

 <PLANET>      <NAME>Venus</NAME>      <MASS UNITS="(Earth = 1)">.815</MASS>      <DAY UNITS="days">116.75</DAY>      <RADIUS UNITS="miles">3716</RADIUS>      <DENSITY UNITS="(Earth = 1)">.943</DENSITY>      <DISTANCE UNITS="million miles">66.8</DISTANCE><!--At perihelion-->  </PLANET> 

To extract comments and put them into <COMMENT> elements, Ill include a rule just for comments:

Listing 4.3 Matching Comments
 <?xml version="1.0"?>  <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">      <xsl:template match="PLANETS">          <HTML>              <xsl:apply-templates/>          </HTML>      </xsl:template>  <xsl:template match="comment()">      <COMMENT>          <xsl:value-of select="."/>      </COMMENT>  </xsl:template>  </xsl:stylesheet> 

Heres the result for Venus, where Ive transformed the comment into a <COMMENT> element:

 Venus  .815  116.75  3716  . 94366.8<  COMMENT>At perihelion</COMMENT> 

Note that here the text for the other elements in the <PLANET> element is also inserted into the output document, because the default rule for each element is to include its text in the output document. Because I havent provided a rule for elements, their text is simply included in the output document.

Matching Nodes with node()

In a pattern, the node node test matches any node except the root node remember, it is really child::node() . Say that you want to use <xsl:copy> to write a stylesheet that copies any XML document (Chapter 3 used <xsl:copy-of> for this purpose.) I might start off as the following example shows. In this case, the template Im using uses the OR operator, which youll see later in this chapter, to match any element or any attribute (this template actually selects itself to keep on copying many levels deep):

 <?xml version="1.0"?>  <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  <xsl:output method="xml"/>      <xsl:template match="@** ">          <xsl:copy>              <xsl:apply-templates select="@**"/>          </xsl:copy>      </xsl:template>  </xsl:stylesheet> 

However, heres the resultnotice that this version, which matches only elements and attributes (@**), doesnt copy whitespace nodes or text nodes:

 <?xml version="1.0" encoding="UTF-8"?>  <PLANETS><PLANET><NAME/><MASS UNITS="(Earth = 1)"/><DAY UNITS="days"/><RADIUS  UNITS="miles"/><DENSITY UNITS="(Earth = 1)"/><DISTANCE UNITS="million miles"/>  </PLANET><PLANET><NAME/><MASS UNITS="(Earth = 1)"/><DAY UNITS="days"/><RADIUS  UNITS="miles"/><DENSITY UNITS="(Earth = 1)"/><DISTANCE UNITS="million miles"/>  </PLANET><PLANET><NAME/><MASS UNITS="(Earth = 1)"/><DAY UNITS="days"/><RADIUS  UNITS="miles"/><DENSITY UNITS="(Earth = 1)"/><DISTANCE UNITS="million miles"/>  </PLANET></PLANETS> 

This is clearly incomplete. If I match to the pattern "@*node()" rather than "@**" , on the other hand, the new template rule will match all nodes except the root node (which is created in the result tree automatically), so it copies whitespace as well as text:

Listing 4.4 A Copying Stylesheet
 <?xml version="1.0"?>  <xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  <xsl:output method="xml"/>    <xsl:template match="@*node()">      <xsl:copy>        <xsl:apply-templates select="@*node()"/>      </xsl:copy>    </xsl:template>  </xsl:stylesheet> 

And heres the new result:

 <?xml version="1.0" encoding="UTF-8"?>  <?xml-stylesheet type="text/xml" href="planets.xsl"?>  <PLANETS>      <PLANET>          <NAME>Mercury</NAME>          <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>      <PLANET>          <NAME>Venus</NAME>          <MASS UNITS="(Earth = 1)">.815</MASS>          <DAY UNITS="days">116.75</DAY>          <RADIUS UNITS="miles">3716</RADIUS>          <DENSITY UNITS="(Earth = 1)">.943</DENSITY>          <DISTANCE UNITS="million miles">66.8</DISTANCE><!--At perihelion-->      </PLANET>          .          .          . 

Matching Text Nodes with text()

You can match the text in a node with the pattern "text()" . Theres usually not much reason to ever use the text node test. XSLT includes a default rule that if no other rules match the text node, the text in that node is inserted into the output document. If you were to make that default rule explicit, it might look like this:

 <xsl:template match="text()">      <xsl:value-of select="."/>  </xsl:template> 

You can override this rule by not sending the text in text nodes to the output document, like this:

 <xsl:template match="text()">  </xsl:template> 

One reason to use the text node test is when you want to match nodes with specific text. Used inside the predicate, as in "NAME[text() = 'Venus']", <NAME> elements where the enclosed name is "Venus" are matched. (Note that you have to be careful about nesting quotation marks so the XSLT processor wont get confused ; for example, this wont work: "NAME[text() = "Venus"]" .) Another reason to use the text node test is when you want to apply some test to text nodes using the XPath string functions (which youll see later in this chapter). For example, Ill match the text node "Earth" in <NAME>Earth</NAME> with the pattern "text()[ starts-with (., 'E')]" .

Stripping out comments

Earlier, you saw that the pattern "@*node()" (which uses the OR operator, , as youll see discussed later) matches everything in planets.xml, including comments. If you want to strip out the comments, you can copy matching to a pattern such as "@**text()" , which preserves only elements, attributes, and text nodes.

Matching Processing Instructions

You can use the pattern processing-instruction() to match processing instructions:

 <xsl:template match="/processing-instruction()">      <I>          Found a processing instruction.      </I>  </xsl:template> 

You can also specify what processing instruction you want to match by giving the name of the processing instruction (excluding the <? and ?> ) as in the following case, where I match the processing instruction <?xml-include?> :

 <xsl:template match="/processing-instruction(xml-include)">      <I>          Found an xml-include processing instruction.      </I>  </xsl:template> 

Distinction Between Root Nodes and Root Elements

One of the major reasons that there is a distinction between the root node at the very beginning of the document and the root element is so you have access to the processing instructions and other nodes in the documents prologue.

That takes care of the node tests that are possible in step patterns. The third and last part of step patterns is predicates.



Inside XSLT
Inside Xslt
ISBN: B0031W8M4K
EAN: N/A
Year: 2005
Pages: 196

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net