1 copyright (c) [2002]. roger l. costello. all rights reserved. using extension elements and...
Post on 22-Dec-2015
228 views
TRANSCRIPT
1Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Using Extension Elements and Extension Functions with XSLT
and XPathRoger L. Costello
XML Technologies
2Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Extension Elements
• The XSL processor understands how to process xsl:template, xsl:apply-templates, xsl:if, xsl:for-each, etc– That is, it understands the vocabulary in the XSL
namespace
• XSL Processor implementers oftentimes provide additional elements that you may use in your stylesheet– These extension elements will belong to a namespace
defined by the implementer
3Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Example Extension Element: instruct the xsl processor to
output to another file• Many of the xsl processor implementers provide an
extension element that instructs the xsl processor to output the contents of the element to another file.– Thus, your stylesheet can generate multiple output files!
XSL Processor
XML
XSL
4Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Vendor-specific
• Each implementor gives the extension element a different name:– saxon calls it: output– xalan calls it: write
5Copyright (c) [2002]. Roger L. Costello. All Rights Reserved. How to use an extension element
1. Declare the namespace that the extension element belongs to:
saxon: xmlns:saxon="http://icl.com/saxon" xalan: xmlns:xalan="http://org.apache.xalan.xslt.extensions.Redirect"2. Indicate that any element that is namespace qualified by the prefix is an extension element, i.e., it has a specific meaning and should be processed using the implementer's code:
saxon: extension-element-prefixes="saxon" xalan: extension-element-prefixes="xalan"3. Use the extension element:
saxon: <saxon:output href="..."> -- anything in here will go to the file specified --- </saxon:output> xalan: <xalan:write file="..."> -- anything in here will go to the file specified --- </xalan:write>
6Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Problem
• Write a stylesheet which outputs the platinum members in one file, the gold members in another file, and the third file is an index to the other two files.
7Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
FitnessCenter.xsl
FitnessCenter.xmlXSL
Processor
gold.xml
new-FitnessCenter.xml
platinum.xml
<PlatinumMembers href="platinum.xml"/><GoldMembers href="gold.xml"/>
8Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
<xsl:copy-of select="xpath"/>
• This element instructs an xsl processor to copy to the output file the element selected by xpath, plus all its descendents.
<xsl:template match="Member"> <xsl:copy-of select="."/></xsl:template>
This instructs the xsl processor to copy everything from <Member> to </Member>i.e., the Member element and all its descendents.
9Copyright (c) [2002]. Roger L. Costello. All Rights Reserved. <?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://icl.com/saxon" extension-element-prefixes="saxon" version="1.0"> <xsl:output method="xml"/>
<xsl:template match="FitnessCenter"> <FitnessCenter> <PlatinumMembers href="platinum.xml"/> <saxon:output href="platinum.xml"> <PlatinumMembers> <xsl:for-each select="Member[@level='platinum']"> <xsl:copy-of select="."/> </xsl:for-each> </PlatinumMembers> </saxon:output> <GoldMembers href="gold.xml"/> <saxon:output href="gold.xml"> <GoldMembers> <xsl:for-each select="Member[@level='gold']"> <xsl:copy-of select="."/> </xsl:for-each> </GoldMembers> </saxon:output> </FitnessCenter> </xsl:template>
</xsl:stylesheet>
See extension-example01
10Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Don’t forget extension-element-prefixes
• The extension-element-prefixes is used to tell the xsl processor, "whenever you encounter an element with any of these prefixes listed here you are to treat it as an extension element, and process it using the implementer's code"
• If you fail to do so the xsl processor will simply output the element literally (see extension-example02)
11Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Extension Functions
• We have seen some of the functions that XSL provides: substring(), contains(), substring-before, etc.
• Many xsl processor implementers provide additional functions. You signify that a function is an extension function by namespace qualifying it.
12Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Dynamic (run-time) Evaluation
• Many xsl processor implementers give you an extension function that enables you to dynamically evaluate an expression.– That is, you can generate the expression on the
fly, or read it in from an external file.
• SAXON provides an extension function called evaluate to do this.
13Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
FitnessCenter.xsl
FitnessCenter.xml XSLProcessor
checkFitnessCenter.xml
results.xml
This file contains expressions that are dynamically evaluated against FitnessCenter.xmlExample: provide an xpath expression that ensures that each Member's level attribute iseither Platinum or Gold, and nothing else.
14Copyright (c) [2002]. Roger L. Costello. All Rights Reserved. <?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saxon="http://icl.com/saxon" extension-element-prefixes="saxon" version="1.0"> <xsl:output method="xml"/> <xsl:variable name="tests" select="document('checkFitnessCenter.xml')"/> <xsl:template match="/"> <xsl:variable name="here" select="."/> <FitnessCenter-results> <xsl:for-each select="$tests//xpath"> <result> <xsl:variable name="xpath" select="."/> <xsl:value-of select="$xpath"/> <xsl:for-each select="$here"> <xsl:choose> <xsl:when test="saxon:evaluate($xpath)"> <xsl:text> SUCCEEDED</xsl:text> </xsl:when> <xsl:otherwise> <xsl:text> FAILED</xsl:text> </xsl:otherwise> </xsl:choose> </xsl:for-each> <xsl:text></xsl:text> </result> </xsl:for-each> </FitnessCenter-results> </xsl:template>
</xsl:stylesheet>
Now any references is to elementsin checkFitnessCenter.xml
Takes us back to referencing elements in FitnessCenter.xml
15Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Using XSLT and XPath to Transform XML Documents that
contain NamespacesRoger L. Costello
XML Technologies
16Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
ProblemSuppose that the document that we are processing is using namespaces:
<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="FitnessCenter.xsl"?>
<FitnessCenter xmlns="http://www.gym.com"> <Member level="platinum"> <Name>Jeff</Name> <Phone type="home">555-1234</Phone> <Phone type="work">555-4321</Phone> <FavoriteColor>lightgrey</FavoriteColor> </Member></FitnessCenter>
Note that we have a default namespace declaration. Thus, FitnessCenter, Member,Name, Phone, and FavoriteColor all belong to the http://www.gym.com namespace.
17Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html"/>
<xsl:template match="/"> <HTML> <BODY> <xsl:apply-templates/> </BODY> </HTML> </xsl:template>
<xsl:template match="*"> <xsl:apply-templates/> </xsl:template>
<xsl:template match="Member">
Your name is: <xsl:value-of select="Name/text()"/> </xsl:template>
<xsl:template match="text()"> <!-- Do nothing --> </xsl:template>
</xsl:stylesheet>(see namespaces-example01)
Output:-- empty --
18Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Why is the output empty?
<xsl:template match="Member"> Your name is: <xsl:value-of select="Name/text()"/></xsl:template>
This template does not match any element in the instance document!This template matches on a Member element in no namespace.However, in our instance document the Member element is in thehttp://www.gym.org namespace, i.e.,
{http://www.gym.com}Member
19Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Namespace Terminology
{http://www.gym.com}Member
Expanded name = The combination of the namespace URI and the local name
Local name
Namespace URI
20Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Namespace Terminology (cont.)
<gym:FitnessCenter xmlns:gym="http://www.gym.com"> <gym:Member> …</gym:FitnessCenter>
<gym:Member>
prefix
21Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
local-name()
• This is a built-in function which returns a string, corresponding to the local name of the element.
<xsl:template match="*"> Local name = <xsl:value-of select="local-name(.)"/> <xsl:apply-templates/></xsl:template>
Output:Local name = FitnessCenterLocal name = MemberLocal name = NameLocal name = PhoneLocal name = PhoneLocal name = FavoriteColor
(see namespaces-example02)
22Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="html"/>
<xsl:template match="/"> <HTML> <BODY> <xsl:apply-templates/> </BODY> </HTML> </xsl:template>
<xsl:template match="*"> <xsl:apply-templates/> </xsl:template>
<xsl:template match="*[local-name()='Member']">
Your name is: <xsl:value-of select=“*[local-name()=‘Name’]/text()"/> </xsl:template>
<xsl:template match="text()"> <!-- Do nothing --> </xsl:template>
</xsl:stylesheet>
(see namespaces-example03)
Output:Your name is: Jeff
23Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Alternatively<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:gym="http://www.gym.com" version="1.0"> <xsl:output method="html"/>
<xsl:template match="/"> <HTML> <BODY> <xsl:apply-templates/> </BODY> </HTML> </xsl:template>
<xsl:template match="*"> <xsl:apply-templates/> </xsl:template>
<xsl:template match="gym:Member">
Your name is: <xsl:value-of select="gym:Name"/> </xsl:template>
<xsl:template match="text()"> <!-- Do nothing --> </xsl:template>
</xsl:stylesheet>
Declare the gym namespace
Match on the Member elementin the gym namespace
Select the Name element inthe gym namespace
(see namespaces-example04)
24Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
namespace-uri()• This is a built-in function which returns a string
corresponding to the namespace URI of the node.
<xsl:template match="*"> Local name = <xsl:value-of select="local-name(.)"/> Namespace URI = <xsl:value-of select="namespace-uri(.)"/> <xsl:apply-templates/></xsl:template>
Output:Local name = FitnessCenterNamespace URI = http://www.gym.comLocal name = MemberNamespace URI = http://www.gym.comLocal name = NameNamespace URI = http://www.gym.comLocal name = PhoneNamespace URI = http://www.gym.com... (see namespaces-example05)
25Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
name() Revisited
• We have seen the name() function before. It returns the name of the node. But what name does it return if the node is in a namespace?– Answer: it returns the element name and its
prefix (this is called the QName, for Qualified Name)
26Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="FitnessCenter.xsl"?><gym:FitnessCenter xmlns:gym="http://www.gym.com"> <gym:Member level="platinum"> <gym:Name>Jeff</gym:Name> <gym:Phone type="home">555-1234</gym:Phone> <gym:Phone type="work">555-4321</gym:Phone> <gym:FavoriteColor>lightgrey</gym:FavoriteColor> </gym:Member></gym:FitnessCenter>
<xsl:template match="*">
Local name = <xsl:value-of select="local-name(.)"/>
Namespace URI = <xsl:value-of select="namespace-uri(.)"/>
Name = <xsl:value-of select="name(.)"/> <xsl:apply-templates/></xsl:template>
27Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Output:Local name = FitnessCenterNamespace URI = http://www.gym.comName = gym:FitnessCenterLocal name = MemberNamespace URI = http://www.gym.comName = gym:MemberLocal name = NameNamespace URI = http://www.gym.comName = gym:NameLocal name = PhoneNamespace URI = http://www.gym.comName = gym:PhoneLocal name = PhoneNamespace URI = http://www.gym.comName = gym:PhoneLocal name = FavoriteColorNamespace URI = http://www.gym.comName = gym:FavoriteColor
(see namespaces-example06)
28Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Identity transform - copying namespace declarations
• Recall our identity transform stylesheet:<xsl:template match="*">
<xsl:element name="{name(.)}">
<xsl:for-each select="@*">
<xsl:attribute name="{name(.)}">
<xsl:value-of select="."/> </xsl:attribute> </xsl:for-each> <xsl:apply-templates/> </xsl:element></xsl:template>
Iterate through eachattribute and add themas attributes onto the element.
29Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
@* does not select namespace declarations!
• The @* will only select non-namespace declaration attributes. It will not select namespace declaration attributes
<Library xmlns="http://www.library.org" xmlns:xsi=" http://www.w3.org/2001/XMLSchema-instance" id="Boston Public Library">
This will be selected by @*
These will not be selected by @*
30Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
Identity transformation for XML documents containing namespaces?
• So how do we create a stylesheet that can copy over namespace declarations, along with the other attributes?– Answer: use the <xsl:copy/> element
31Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
<xsl:copy/>
• This element will copy the current element and all namespace declarations to the output file.
• Shallow copy (copy current node)• Cf: <xsl:copy-of />
– Deep copy (Copy current tree )– copy all attributes and namespace nodes– copy all descendants
32Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml"/>
<xsl:template match="* | @*"> <xsl:copy> <xsl:apply-templates select="@*"/> <xsl:apply-templates/> </xsl:copy> </xsl:template>
</xsl:stylesheet>
(see namespaces-example07)
The problem with this identity transform stylesheet is that it's not set upto allow us to make changes to elements/attributes.
33Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml"/>
<xsl:template match="*"> <xsl:element name="{name(.)}"> <xsl:copy-of select="namespace::*" /> <xsl:for-each select="@*"> <xsl:attribute name="{name(.)}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:for-each>
<xsl:apply-templates/>
</xsl:element> </xsl:template>
</xsl:stylesheet>
Error! Attemptingto create anelement in anamespace, butthe namespacehas not beendeclared yet!
34Copyright (c) [2002]. Roger L. Costello. All Rights Reserved.
<?xml version="1.0"?><xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml"/>
<xsl:template match="*"> <xsl:element name="{name(.)}" namespace="{namespace-uri(.)}"> <xsl:copy-of select="namespace::*" /> <xsl:for-each select="@*"> <xsl:attribute name="{name(.)}" namespace="{namespace-uri(.)}"> <xsl:value-of select="."/> </xsl:attribute> </xsl:for-each>
<xsl:apply-templates/>
</xsl:element> </xsl:template>
</xsl:stylesheet>
Simultaneouslydeclare theelement and its namespace
Simultaneouslydeclare theattribute and its namespace
(see namespaces-example08)