440 likes | 692 Views
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
E N D
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 elements associated 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 JAXP import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.xml.sax.InputSource; // For Xalan XPath API import 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 Run D:\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.xml XPath: //*[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 XSLT • documents: • javax.xml.transform Interface Source • All Known Implementing Classes: • DOMSource, SAXSource, StreamSource • javax.xml.transformInterface Result • All Known Implementing Classes: • DOMResult, SAXResult, StreamResult
XSLT Programming in Java A 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 7 import 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 7 import 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 particular type of XML document. Suppose too that we have a new document with similar semantics but with a different structure. We don’t want to modify our old handler. Instead we want to do a translation of the new document to the old format.
JAXP/SAX : : SAX : : JAXP/SAX : : SAX : : SAXParser Application TransformerHandler (3) Register (2) Register Content Handler SAX Result SAX Parser Content Handler Input XML SAX Events Transform SAX Events (4) (5) (7) (6) Register (1) XSLT XML and Java, Second Edition, Developing Web Applications, Hiroshi Maruyama, et.al. 2002
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>jjc@jclark.com</ContactTo> </Author> <Author> <AuthorName>Steve DeRose</AuthorName> <ContactTo>Steven_DeRose@Brown.edu</ContactTo> </Author> </Book>
<Book> <PublishedDate>16 November 1999</PublishedDate> <Author> <AuthorName>James Clark</AuthorName> <ContactTo>jjc@jclark.com</ContactTo> </Author> </Book> </Books>
We have a handler for Books.xml // Adapted from XML and Java Chapter 7 import 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, contactTo=jjc@jclark.com), Author(authorName=Steve DeRose, contactTo=Steven_DeRose@Brown.edu)]), Book(publishedDate=16 November 1999, authors= [Author(authorName=James Clark, contactTo=jjc@jclark.com)])]
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>jjc@jclark.com</email> </editor>
<editor> <name>Steve DeRose</name> <email>Steven_DeRose@Brown.edu</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>jjc@jclark.com</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.java import 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, contactTo=jjc@jclark.com), Author(authorName=Steve DeRose, contactTo=Steven_DeRose@Brown.edu)]), Book(publishedDate=16 November 1999, authors=[Author(authorName=James Clark, contactTo=jjc@jclark.com)])]