More XPATH and XSLT Xpath and Namespaces Xpath Programming in Java XSLT Default Rules XSLT...

44
More XPATH and XSLT • Xpath and Namespaces • Xpath Programming in Java • XSLT Default Rules • XSLT Programming in Java
  • date post

    22-Dec-2015
  • Category

    Documents

  • view

    271
  • download

    0

Transcript of More XPATH and XSLT Xpath and Namespaces Xpath Programming in Java XSLT Default Rules XSLT...

More XPATH and XSLT

• Xpath and Namespaces

• Xpath Programming in Java

• XSLT Default Rules

• XSLT Programming in Java

Xpath and Namespaces

• Namespaces are widely used

• In a SOAP message, for example, every element is qualified with a namespace

• Here we will look at how namespaces are handled in XPath

Xpath and Namespaces

Consider an Xpath expression

/Envelope/Header/Signature

Now, with namespaces included

/SOAP-ENV:Envelope/SOAP-ENV:Header/dsig:Signature

What is wrong with this approach?

Namespace prefixes may vary. SE:Envelope is a legal SOAP element if the prefix SE is associated with

http://schemas.xmlsoap.org/soap/envelope

Xpath and Namespaces

Suppose we want to select all the Signature elementsassociated with the namespace http://www.w3.org/2000/09/xmldsig#

Write the Xpath expression as follows

//*[namespace-uri()=“http://www.w3.org/2000/09/xmldsig#” and local-name() = “Signature”]

Xpath Programming in Java

• We can evaluate an Xpath expression from within a Java program.

• The following is an example using Namespaces.

XPathTest.java<?xml version="1.0" encoding="UTF-8"?><Signature Id="MyFirstSignature" xmlns= "http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethod Algorithm= "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> <SignatureMethod Algorithm= "http://www.w3.org/2000/09/xmldsig#dsa-sha1"/> <Reference URI= "http://www.w3.org/TR/2000/REC-xhtml1-20000126/"> <Transforms> <Transform Algorithm= "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/> </Transforms>

<DigestMethod Algorithm= "http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk= </DigestValue> </Reference> </SignedInfo>

XPathTest.java

// XML and Java Second Ed. Chapter 7// For JAXPimport javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.xml.sax.InputSource;

// For Xalan XPath APIimport org.apache.xpath.XPathAPI;import org.w3c.dom.traversal.NodeIterator; import org.w3c.dom.Node;import org.w3c.dom.Document;

public class XPathTest { public static void main(String[] args) throws Exception { String xmlFilePath = args[0]; String xPath = args[1];

System.out.println("Input XML File: " + xmlFilePath); System.out.println("XPath: " + xPath);

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder parser = factory.newDocumentBuilder();

InputSource in = new InputSource(xmlFilePath); Document doc = parser.parse(in);

Node contextNode = doc.getDocumentElement(); NodeIterator i = XPathAPI.selectNodeIterator(contextNode, xPath); int count = 0; Node node; // For each node while ((node = i.nextNode()) != null) { // Outputs the node to System.out System.out.println(node.toString()); count++; } System.out.println("" + count + " match(es)"); }}

Example RunD:\McCarthy\www\95-733\examples\xpath\HandleNamespaces>java XPathTest MyFirstSignature.xml "//*[local-name()='DigestValue' and namespace-uri()='http://www.w3.org/2000/09/xmldsig#']“

Input XML File: MyFirstSignature.xmlXPath: //*[local-name()='DigestValue' and namespace-uri()='http://www.w3.org/2000/09/xmldsig#']

<DigestValue>j6lwx3rvEPO0vKtMup4NbeVu8nk=</DigestValue>1 match(es)

XSLT Default Rules

<xsl:template match-”*|/”> <xsl:apply-templates></xsl:template>

<xsl:template match=“text() | @*”> <xsl:value-of select=“.”/></xsl:template>

<xsl:template match=“processing-instruction() | comment()” />

XSLT Programming in Java

Two important interfaces to represent the XML and XSLTdocuments:

javax.xml.transform

Interface Source All Known Implementing Classes:

DOMSource, SAXSource, StreamSource

javax.xml.transform Interface Result All Known Implementing Classes: DOMResult, SAXResult, StreamResult

XSLT Programming in JavaA Factory to build XSLT Transformers

javax.xml.transform

Class TransformerFactory

Ask for a Transformer with an associated XSLT document:

Transformer t = newTransformer(Source source)

Use t to do the transformation

voidtransform(Source xmlSource, Result outputTarget)           Process the source tree to the output result.

XSLT Stream to Stream Example

// XML and Java Chapter 7import javax.xml.transform.TransformerFactory;import javax.xml.transform.Transformer;import javax.xml.transform.stream.StreamSource;import javax.xml.transform.stream.StreamResult;

public class XSLTStreamTest { public static void main(String[] args) throws Exception { // args[0] specifies the path to the input XSLT stylesheet String xsltURL = args[0]; // args[1] specifies the path to the input XML document String xmlURL = args[1];

// Creates instances of StreamSource for the stylesheet StreamSource xslt = new StreamSource(xsltURL); // Creates instances of StreamSource for the input document StreamSource xml = new StreamSource(xmlURL);

// Creates an instance of TransformerFactory TransformerFactory factory = TransformerFactory.newInstance(); // Creates an instance of Transformer Transformer transformer = factory.newTransformer(xslt); // Executes the Transformer transformer.transform(xml, new StreamResult(System.out)); }}

XSLT DOM to DOM Example// XML and Java Chapter 7import javax.xml.transform.TransformerFactory;import javax.xml.transform.Transformer;import javax.xml.transform.dom.DOMSource;import javax.xml.transform.dom.DOMResult;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.apache.xml.serialize.OutputFormat;import org.apache.xml.serialize.XMLSerializer;import org.w3c.dom.Node;import org.w3c.dom.Element;import org.w3c.dom.Document;import org.w3c.dom.DocumentFragment;

public class XSLTDOMTest { public static void main(String[] args) throws Exception { // args[0] specifies the path to the input XSLT stylesheet String xsltURL = args[0]; // args[1] specifies the path to the input XML document String xmlURL = args[1];

// Creates an instance of DocumentBuilderFactory. DocumentBuilderFactory dFactory = DocumentBuilderFactory.newInstance(); dFactory.setNamespaceAware(true); // Creates an instance of DocumentBuilder DocumentBuilder parser = dFactory.newDocumentBuilder();

// Creates a DOM instance of the stylesheet Document xsltDoc = parser.parse(xsltURL); // Creates a DOM instance of the input document Document xmlDoc = parser.parse(xmlURL);

// Creates an instance of TransformerFactory TransformerFactory tFactory = TransformerFactory.newInstance(); // Checks if the factory supports DOM or not if(!tFactory.getFeature(DOMSource.FEATURE) || !tFactory.getFeature(DOMResult.FEATURE)) throw new Exception("DOM is not supported");

// Creates instances of DOMSource and DOMResult DOMSource xsltDOMSource = new DOMSource(xsltDoc); DOMSource xmlDOMSource = new DOMSource(xmlDoc); DOMResult domResult = new DOMResult();

// Creates an instance of Transformer Transformer transformer = tFactory.newTransformer(xsltDOMSource);

// Executes the Transformer transformer.transform(xmlDOMSource, domResult);

// Gets the result Node resultNode = domResult.getNode();

// Prints the response OutputFormat formatter = new OutputFormat(); formatter.setPreserveSpace(true); XMLSerializer serializer = new XMLSerializer(System.out, formatter); switch (resultNode.getNodeType()) { case Node.DOCUMENT_NODE: serializer.serialize((Document)resultNode); break; case Node.ELEMENT_NODE: serializer.serialize((Element)resultNode); break; case Node.DOCUMENT_FRAGMENT_NODE: serializer.serialize((DocumentFragment)resultNode); break; default: throw new Exception("Unexpected node type"); }}}

SAX Event Translation Using XSLT

Suppose we have a SAX handler written for a particulartype of XML document.

Suppose too that we have a new document with similarsemantics but with a different structure.

We don’t want to modify our old handler. Instead we wantto do a translation of the new document to the old format.

XML and Java, Second Edition, Developing Web Applications, Hiroshi Maruyama, et.al. 2002

SAX Parser

ContentHandler

SAXResult

ContentHandler

TransformInput XML

JAXP/SAX : :

SAX::

JAXP/SAX : :

SAX Events SAX Events

TransformerHandlerSAXParser

SAX::

Application

(2)Register

(3)Register

Register(1)

(4) (5) (6) (7)

XSLT

Books.xml<?xml version="1.0" encoding="UTF-8"?><Books xmlns="http://www.example.com/xmlbook2/chap07/"> <Book> <PublishedDate>16 November 1999</PublishedDate> <Author> <AuthorName>James Clark</AuthorName> <ContactTo>[email protected]</ContactTo> </Author> <Author> <AuthorName>Steve DeRose</AuthorName> <ContactTo>[email protected]</ContactTo> </Author> </Book>

<Book> <PublishedDate>16 November 1999</PublishedDate> <Author> <AuthorName>James Clark</AuthorName> <ContactTo>[email protected]</ContactTo> </Author> </Book></Books>

We have a handler for Books.xml// Adapted from XML and Java Chapter 7import java.util.Vector;import org.xml.sax.Attributes;import org.xml.sax.SAXException;import org.xml.sax.helpers.DefaultHandler;

// Imports for main() to test the Handler

import org.xml.sax.InputSource;import org.xml.sax.XMLReader;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;

public class BookHandler extends DefaultHandler { // An array to store the results final Vector books; public BookHandler() { this.books = new Vector(); }

// Instance variables temporarily used for processing Book currentBook = null; Author currentAuthor = null; StringBuffer buf = new StringBuffer();

class Book { String publishedDate; Vector authors = new Vector(); public String toString() { return ("Book(publishedDate=" + publishedDate + ", authors=" + authors+")"); } } class Author { String authorName; String contactTo; public String toString() { return ("Author(authorName=" + authorName + ", contactTo=" + contactTo + ")"); } }

public void endDocument() throws SAXException { System.out.println(books); }

public void startElement(String uri,String localName, String qName, Attributes attributes) throws SAXException { if ("Book".equals(qName)) { currentBook = new Book(); return; }

if ("Author".equals(qName)) { currentAuthor = new Author(); return; } buf.setLength(0); }

public void endElement(String uri, String localName, String qName) throws SAXException { if ("Book".equals(qName)) { books.addElement(currentBook); return; }

if ("Author".equals(qName)) { currentBook.authors.addElement(currentAuthor); return; } if ("PublishedDate".equals(qName)) currentBook.publishedDate = buf.toString(); else if ("AuthorName".equals(qName)) currentAuthor.authorName = buf.toString(); else if ("ContactTo".equals(qName)) currentAuthor.contactTo = buf.toString(); buf.setLength(0); }

public void characters(char[] ch, int start, int length) throws SAXException { buf.append(new String(ch, start, length)); }

public static void main(String args[]) throws Exception {

// Create and InputSource on a book.xml document InputSource xml = new InputSource(args[0]); // Creates a SAX parser SAXParserFactory pFactory = SAXParserFactory.newInstance(); SAXParser parser = pFactory.newSAXParser(); XMLReader xmlReader = parser.getXMLReader();

// Set up this class as the handler xmlReader.setContentHandler(new BookHandler()); // Parses the input XML (which is of the appropriate form) xmlReader.parse(xml);

}}

D:..\examples\XSLTFilter> java BookHandler Books.xml

[Book(publishedDate=16 November 1999, authors=[Author(authorName=James Clark,[email protected]),

Author(authorName=Steve DeRose, [email protected])]),

Book(publishedDate=16 November 1999, authors=[Author(authorName=James Clark, [email protected])])]

But no handler for sample.xml…<?xml version="1.0" encoding="UTF-8"?><W3Cspecs xmlns="http://www.example.com/xmlbook2/chap07/"> <spec title="XML Path Language (XPath) Version 1.0" url="http://www.w3.org/TR/xpath"> <date type="REC">16 November 1999</date> <editors> <editor> <name>James Clark</name> <email>[email protected]</email> </editor>

<editor> <name>Steve DeRose</name> <email>[email protected]</email> </editor> </editors> </spec> <spec title="XSL Transformations (XSLT) Version 1.0" url="http://www.w3.org/TR/xslt"> <date type="REC">16 November 1999</date> <editors> <editor> <name>James Clark</name> <email>[email protected]</email> </editor> </editors> </spec></W3Cspecs>

We write an XSLT program…<?xml version="1.0" encoding="UTF-8"?><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.example.com/xmlbook2/chap07/"> <xsl:output method="xml" encoding="UTF-8"/>

<xsl:template match="*[local-name()='W3Cspecs']"> <Books><xsl:apply-templates/></Books> </xsl:template>

<xsl:template match="*[local-name()='spec']"> <Book><xsl:apply-templates/></Book> </xsl:template>

<xsl:template match="*[local-name()='date']"> <PublishedDate><xsl:apply-templates/></PublishedDate> </xsl:template>

<xsl:template match="*[local-name()='editor']"> <Author><xsl:apply-templates/></Author> </xsl:template>

<xsl:template match="*[local-name()='name']"> <AuthorName><xsl:apply-templates/></AuthorName> </xsl:template>

<xsl:template match="*[local-name()='email']"> <ContactTo><xsl:apply-templates/></ContactTo> </xsl:template>

<xsl:template match="@*"> <xsl:value-of select="name()"/>=<xsl:value-of select="."/> </xsl:template></xsl:stylesheet>

In book but no need.

And write a program to pipe the XSLT output to

BookHandler.javaimport javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import javax.xml.transform.TransformerFactory;import javax.xml.transform.sax.SAXSource;import javax.xml.transform.sax.SAXResult;import javax.xml.transform.sax.SAXTransformerFactory;import javax.xml.transform.sax.TransformerHandler;import javax.xml.transform.stream.StreamSource;import org.xml.sax.InputSource;import org.xml.sax.XMLReader;

public class XSLTSAXTest {

public static void main(String[] args) throws Exception { // args[0] specifies the URI for the XSLT stylesheet String xsltURL = args[0]; // args[1] specifies the URI for the input XML document String xmlURL = args[1];

// Creates a stream source for the stylesheet StreamSource xslt = new StreamSource(xsltURL); // Creates an input source for the input document InputSource xml = new InputSource(xmlURL);

// Creates a SAX parser SAXParserFactory pFactory = SAXParserFactory.newInstance(); pFactory.setNamespaceAware(true); SAXParser parser = pFactory.newSAXParser(); XMLReader xmlReader = parser.getXMLReader();

// Creates an instance of TransformerFactory TransformerFactory tFactory = TransformerFactory.newInstance();

// Checks if the TransformingFactory supports SAX or not if (!tFactory.getFeature(SAXSource.FEATURE)) throw new Exception("SAX is not supported");

// Casts TransformerFactory to SAXTransformerFactory SAXTransformerFactory stFactory = ((SAXTransformerFactory)tFactory); // Creates a TransformerHandler with the stylesheet TransformerHandler tHandler = stFactory.newTransformerHandler(xslt); // Sets the TransformerHandler to the SAXParser xmlReader.setContentHandler(tHandler); // Sets the application ContentHandler // to the TransformerHandler tHandler.setResult(new SAXResult(new BookHandler()));

// Parses the input XML xmlReader.parse(xml); }}

D:..\examples\XSLTSAXFilter>java XSLTSAXTest sample-4.xsl sample.xml

[Book(publishedDate=16 November 1999, authors=[Author(authorName=James Clark, [email protected]), Author(authorName=Steve DeRose, [email protected])]),

Book(publishedDate=16 November 1999, authors=[Author(authorName=James Clark, [email protected])])]