1 / 34

Using Extension Elements and Extension Functions with XSLT and XPath

Using Extension Elements and Extension Functions with XSLT and XPath. Roger L. Costello XML Technologies. 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

katima
Télécharger la présentation

Using Extension Elements and Extension Functions with XSLT and XPath

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Using Extension Elements and Extension Functions with XSLT and XPath Roger L. Costello XML Technologies

  2. 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

  3. 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

  4. Vendor-specific • Each implementor gives the extension element a different name: • saxon calls it: output • xalan calls it: write • xsl:result-document // xslt20 • example in xslt20

  5. 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>

  6. 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.

  7. platinum.xml XSL Processor <PlatinumMembers href="platinum.xml"/> <GoldMembers href="gold.xml"/> FitnessCenter.xml new-FitnessCenter.xml gold.xml FitnessCenter.xsl

  8. <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.

  9. <?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

  10. 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)

  11. 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.

  12. 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.

  13. XSL Processor FitnessCenter.xml results.xml checkFitnessCenter.xml FitnessCenter.xsl This file contains expressions that are dynamically evaluated against FitnessCenter.xml Example: provide an xpath expression that ensures that each Member's level attribute is either Platinum or Gold, and nothing else.

  14. <?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 elements in checkFitnessCenter.xml Takes us back to referencing elements in FitnessCenter.xml

  15. Using XSLT and XPath to Transform XML Documents that contain Namespaces Roger L. Costello XML Technologies

  16. Problem Suppose 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.

  17. <?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> Output: -- empty -- (see namespaces-example01)

  18. 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 the http://www.gym.org namespace, i.e., {http://www.gym.com}Member

  19. Namespace Terminology {http://www.gym.com}Member Local name Namespace URI Expanded name = The combination of the namespace URI and the local name

  20. Namespace Terminology (cont.) <gym:FitnessCenter xmlns:gym="http://www.gym.com"> <gym:Member> … </gym:FitnessCenter> <gym:Member> prefix

  21. 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 = FitnessCenter Local name = Member Local name = Name Local name = Phone Local name = Phone Local name = FavoriteColor (see namespaces-example02)

  22. <?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> Output: Your name is: Jeff (see namespaces-example03)

  23. 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 element in the gym namespace Select the Name element in the gym namespace (see namespaces-example04)

  24. namespace-uri() <xsl:template match="*"> Local name = <xsl:value-of select="local-name(.)"/> Namespace URI = <xsl:value-of select="namespace-uri(.)"/> <xsl:apply-templates/> </xsl:template> • This is a built-in function which returns a string corresponding to the namespace URI of the node. Output: Local name = FitnessCenter Namespace URI = http://www.gym.com Local name = Member Namespace URI = http://www.gym.com Local name = Name Namespace URI = http://www.gym.com Local name = Phone Namespace URI = http://www.gym.com ... (see namespaces-example05)

  25. 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)

  26. <?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>

  27. Output: Local name = FitnessCenter Namespace URI = http://www.gym.com Name = gym:FitnessCenter Local name = Member Namespace URI = http://www.gym.com Name = gym:Member Local name = Name Namespace URI = http://www.gym.com Name = gym:Name Local name = Phone Namespace URI = http://www.gym.com Name = gym:Phone Local name = Phone Namespace URI = http://www.gym.com Name = gym:Phone Local name = FavoriteColor Namespace URI = http://www.gym.com Name = gym:FavoriteColor (see namespaces-example06)

  28. 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 each attribute and add them as attributes onto the element.

  29. @* 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 @*

  30. 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

  31. <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

  32. <?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 up to allow us to make changes to elements/attributes.

  33. <?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! Attempting to create an element in a namespace, but the namespace has not been declared yet!

  34. <?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> Simultaneously declare the element and its namespace Simultaneously declare the attribute and its namespace (see namespaces-example08)

More Related