defaultNs = null;
prefixMap = new HashMap<String, String>();
}
+
+ public static SimpleNamespaceContext namespaces() {
+ return new SimpleNamespaceContext();
+ }
/**
* Constructs a context with a single prefix.
--- /dev/null
+/*
+ * Copyright 2005-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wamblee.xml;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathFactory;
+
+/**
+ * Represents a namespace context and is a factory for creating xpath expressions.
+ * @author Erik Brakkee
+ */
+public class XPathContext {
+ private XPath xpath;
+
+ /**
+ * Constructs the context.
+ * @param aContext Namespaces.
+ */
+ public XPathContext(NamespaceContext aContext) {
+ xpath = XPathFactory.newInstance().newXPath();
+ xpath.setNamespaceContext(aContext);
+ }
+
+ public static XPathContext xpathcontext(NamespaceContext aContext) {
+ return new XPathContext(aContext);
+ }
+
+ /**
+ * Creates the expression.
+ * @param aExpression XPath expression.
+ * @return Xpath expression.
+ * @throws XMLException
+ */
+ public XPathExpression createExpression(String aExpression) throws XMLException {
+ return new XPathExpression(xpath, aExpression);
+ }
+
+ /**
+ * To get access to the lower level API.
+ * @return Lower level API.
+ */
+ public XPath getXpath() {
+ return xpath;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2005-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wamblee.xml;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * XPath expression.
+ *
+ * @author Erik Brakkee
+ */
+public class XPathExpression {
+ private String expressionString;
+ private javax.xml.xpath.XPathExpression expression;
+
+ /**
+ * Constructs the expression. Users typically use {@link XPathContext#createExpression(String)} instead
+ * of this constructor.
+ *
+ * @param aXpath Xpath interface.
+ * @param aExpression Expression.
+ * @throws XMLException In case of problems.
+ */
+ public XPathExpression(XPath aXpath, String aExpression)
+ throws XMLException {
+ expressionString = aExpression;
+ try {
+ expression = aXpath.compile(aExpression);
+ } catch (XPathExpressionException e) {
+ throw new XMLException("Could not compile xpath expression '" +
+ aExpression + "'", e);
+ }
+ }
+
+ /**
+ * Evaluates the xpath expression to a string.
+ * @param aDocument Document
+ * @return Value.
+ * @throws XMLException In case of problems.
+ */
+ public String stringEval(XMLDocument aDocument) throws XMLException {
+ return (String)evaluateImpl(aDocument, XPathConstants.STRING);
+ }
+
+ /**
+ * Evaluates the xpath expression to a boolean.
+ * @param aDocument Document
+ * @return Value.
+ * @throws XMLException In case of problems.
+ */
+ public boolean booleanEval(XMLDocument aDocument) throws XMLException {
+ return (Boolean)evaluateImpl(aDocument, XPathConstants.BOOLEAN);
+ }
+
+ /**
+ * Evaluates the xpath expression to a node list.
+ * @param aDocument Document
+ * @return Value.
+ * @throws XMLException In case of problems.
+ */
+ public NodeList nodelistEval(XMLDocument aDocument) throws XMLException {
+ return (NodeList)evaluateImpl(aDocument, XPathConstants.NODESET);
+ }
+
+ /**
+ * Evaluates the xpath expression to a Node.
+ * @param aDocument Document
+ * @return Value.
+ * @throws XMLException In case of problems.
+ */
+ public Node nodeEval(XMLDocument aDocument) throws XMLException {
+ return (Node)evaluateImpl(aDocument, XPathConstants.NODE);
+ }
+
+ /**
+ * Evaluates the xpath expression to a number.
+ * @param aDocument Document
+ * @return Value.
+ * @throws XMLException In case of problems.
+ */
+ public Double numberEval(XMLDocument aDocument) throws XMLException {
+ return (Double)evaluateImpl(aDocument, XPathConstants.NUMBER);
+ }
+
+ /**
+ * @return Low-level xpath expression object.
+ */
+ public javax.xml.xpath.XPathExpression getExpression() {
+ return expression;
+ }
+
+ /**
+ * @return XPath expression.
+ */
+ public String getExpressionString() {
+ return expressionString;
+ }
+
+
+ private Object evaluateImpl(XMLDocument aDocument, QName aResultType) throws XMLException {
+ try {
+ return expression.evaluate(aDocument.getDocument(),
+ aResultType);
+ } catch (XPathExpressionException e) {
+ throw new XMLException("Problem evaluating expression '" +
+ expressionString + "' on document '" + aDocument.print(true) +
+ "'", e);
+ }
+ }
+
+}
* limitations under the License.
*/
/**
- * Utilities for XML processing.
+ * <p>
+ * Utilities for XML processing. The aim of this package is to simplify the
+ * common tasks of parsing, validating, and transforming XML files and to
+ * provide support for XPath. The utlities simply use the standard Java SE APIs
+ * but are much easier to use. For cases where more advanced functionality is required,
+ * the classes provide access to the underlying Java SE types. The implementation is
+ * based on DOM level 3 parsing.
+ * </p>
+ *
+ * <p>
+ * Classes {@link org.wamblee.xml.XMLDocument}, {@link org.wamblee.xml.XMLSchema}, and
+ * {@link org.wamblee.xml.XSLTransformation} provide parsing, validation, and transformation
+ * of XML files. The {@link org.wamblee.xml.XMLDocument} class provides various static
+ * methods as entry point for this functionality, simplifying the code a lot when
+ * static imports are used. The API design uses a fluent interfaces style. For instance,
+ * to parse, validate, and transform an XML file, one can write:
+ * </p>
+ * <pre>
+ * import static org.wamblee.xml.XMLDocument;
+ * ...
+ * XMLDocument doc = xmldocument(new File("x.xml").toURI()).validate(new File("x.xsd").toURI()).transform(new File("x.xsl").toURI());
+ * </pre>
+ *
+ * <p>
+ * In addition, a URI resolver {@link org.wamblee.xml.ClasspathUriResolver} is provided to allow resolution of
+ * documents on the classpath.
+ * </p>
+ *
+ * <p>
+ * For XPath the following classes are provided:
+ * </p>
+ * <ul>
+ * <li> {@link org.wamblee.xml.SimpleNamespaceContext}: An generic implementation of {@link javax.xml.namespace.NamespaceContext}.
+ * </li>
+ * <li> {@link org.wamblee.xml.XPathContext}: A factory of <code>XPathExpression</code> objects based on a given namespace
+ * context.
+ * </li>
+ * <li> {@link org.wamblee.xml.XPathExpression}: The interface for working with XPath.
+ * </li>
+ * </ul>
+ * f
+ * <p>
+ * For instance to apply an XPath expression to an XML document:
+ * </p>
+ * <pre>
+ * NamespaceContext context = new XPathContext(new SimpleNamespaceContext()
+ * .addPrefix("n", "http://example.com/1")
+ * .addPrefix("m", "http://example.com/2"));
+ * XMLDocument doc = new XMLDocument(new File("xpathexample.xml").toURI());
+ * String value = context.createExpression("/n:root/m:x").stringEval(doc);
+ * </pre>
+ * <p>
+ * Or, using static imports:
+ * </p>
+ * <pre>
+ * NamespaceContext context = xpathcontext(namespaces()
+ * .addPrefix("n", "http://example.com/1")
+ * .addPrefix("m", "http://example.com/2"));
+ * XMLDocument doc = xmldocument(new File("xpathexample.xml").toURI());
+ * String value = context.createExpression("/n:root/m:x").stringEval(doc);
+ * </pre>
*/
package org.wamblee.xml;
--- /dev/null
+/*
+ * Copyright 2005-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.wamblee.xml;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import static junit.framework.TestCase.*;
+import static org.wamblee.xml.XMLDocument.*;
+import static org.wamblee.xml.XPathContext.*;
+import static org.wamblee.xml.SimpleNamespaceContext.*;
+
+public class XPathExpressionTest {
+
+ private XPathContext context;
+ private XMLDocument doc;
+
+ @Before
+ public void setUp() throws XMLException, URISyntaxException, IOException {
+ context = xpathcontext(namespaces().addPrefix("n", "http://example.com/1").addPrefix("m", "http://example.com/2"));
+ doc = xmldocument(getClass().getResource("xpathexample.xml").toURI());
+ }
+
+ @Test(expected = XMLException.class)
+ public void testInvalidXpath() throws XMLException {
+ context.createExpression("a[");
+ }
+
+ @Test
+ public void testStringVal() throws XMLException {
+ String value = context.createExpression("/n:root/m:x").stringEval(doc);
+ assertEquals("hallo", value.trim());
+ }
+
+ @Test
+ public void testBooleanVal() throws XMLException {
+ assertTrue(context.createExpression("/n:root/m:x").booleanEval(doc));
+ assertFalse(context.createExpression("unknownelement").booleanEval(doc));
+ }
+
+ @Test
+ public void testNummberVal() throws XMLException {
+ assertEquals(1.0d, context.createExpression("count(/n:root/m:x)").numberEval(doc));
+ assertEquals(11.0d, context.createExpression("//n:elem").numberEval(doc));
+ }
+
+ @Test
+ public void testNodeVal() throws XMLException {
+ Node node = context.createExpression("/n:root/n:elem").nodeEval(doc);
+ assertTrue(node instanceof Element);
+ assertEquals("11", node.getTextContent().trim());
+ assertEquals("elem", node.getLocalName());
+ assertEquals("http://example.com/1", node.getNamespaceURI());
+ }
+
+ @Test
+ public void testNodeSetVal() throws XMLException {
+ NodeList nodelist = context.createExpression("/n:root/n:elem").nodelistEval(doc);
+ assertEquals(2, nodelist.getLength());
+ assertEquals("11", nodelist.item(0).getTextContent().trim());
+ assertEquals("22", nodelist.item(1).getTextContent().trim());
+ }
+}
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
--- /dev/null
+<n:root xmlns:n="http://example.com/1">
+ <m:x xmlns:m="http://example.com/2">
+ hallo
+ </m:x>
+ <n:elem>11</n:elem>
+ <n:elem>22</n:elem>
+</n:root>
\ No newline at end of file