1 copyright (c) [2002]. roger l. costello. all rights reserved. using extension elements and...

Post on 22-Dec-2015

228 Views

Category:

Documents

2 Downloads

Preview:

Click to see full reader

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)

top related