Posts Tagged ‘XPath’
Bug in Apache Camel 1.6
As discussed here, XPath expressions don’t reset streams in 1.6.0, causing any evaluations but the first to succeed.
https://issues.apache.org/jira/browse/CAMEL-1337
If you are using FUSE 4.1.0.0, upgrading to 4.1.0.1 fixes the issue.
You can work around it, though:
from("jbi:endpoint:http://www.fernandoribeiro.eti.br/SampleService/SamplePort").convertBodyTo(Document.class).choice().when().xpath("/Root/Element1 = 'Value1'").to("direct:Route1").when().xpath("/Root/Element1 = 'Value2'").to("direct:Route2");
xs:choice in Apache XMLBeans
When using it, you may need to iterate through several element lists:
import org.apache.xmlbeans.XmlCursor;
...
final XmlCursor cur = el.newCursor();
cur.selectPath("declare namespace simplesassim='http://fernandoribeiro.eti.br'; simplesassim:Element1 | simplesassim:Element2");
while (cur.toNextSelection()) {
final Object obj = cur.getObject();
...
}
http://xmlbeans.apache.org/docs/2.0.0/guide/conSelectingXMLwithXQueryPathXPath.html
Using nilled in XPath
Even though it was introduced in 2007, it ain’t supported by Apache Xalan (and therefore the JRE) yet. The only alternative seems to be Saxon-SA.
Document.xml (not pointing to the schema)
<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Element xsi:nil="true"/>
</Root>
Document.xml (pointing to the schema)
<?xml version="1.0" encoding="UTF-8"?>
<Root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="Schema.xsd">
<Element xsi:nil="true"/>
</Root>
Schema.xsd
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Root">
<xs:complexType>
<xs:sequence>
<xs:element name="Element" nillable="true">
<xs:complexType/>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Stylesheet.xsl
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/Root">
<Root>
<Element>
<xsl:choose>
<xsl:when test="nilled(Element)">0</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</Element>
</Root>
</xsl:template>
</xsl:stylesheet>
SaxonSASample1.java
- Doesn’t require the document to point to the location of the schema.
- Uses a transformer.
import java.io.FileReader;
import net.sf.saxon.FeatureKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.xml.sax.InputSource;
import static java.lang.System.out;
import com.saxonica.SchemaAwareTransformerFactory;
public final class SaxonSample {
public static void main(final String[] args) throws Exception {
final SchemaAwareTransformerFactory factory = (SchemaAwareTransformerFactory) TransformerFactory.newInstance(); // ensure javax.xml.transform.TransformerFactory system property is set to com.saxonica.SchemaAwareTransformerFactory
factory.addSchema(new StreamSource("Schema.xsd"));
factory.setAttribute(FeatureKeys.SCHEMA_VALIDATION_MODE, "strict");
final Transformer transformer = factory.newTransformer(new StreamSource(new FileReader("Stylesheet.xsl")));
transformer.transform(new SAXSource(new InputSource(new FileReader("Document.xml"))), new StreamResult(out));
}
}
SaxonSASample2.java
- Requires the document to point to the location of the schema.
- Uses a transformer.
import java.io.FileReader;
import net.sf.saxon.FeatureKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.xml.sax.InputSource;
import static java.lang.System.out;
public final class SaxonSASample2 {
public static void main(final String[] args) throws Exception {
final TransformerFactory factory = TransformerFactory.newInstance(); // ensure javax.xml.transform.TransformerFactory system property is set to com.saxonica.SchemaAwareTransformerFactory
factory.setAttribute(FeatureKeys.SCHEMA_VALIDATION_MODE, "strict");
final Transformer transformer = factory.newTransformer(new StreamSource(new FileReader("Stylesheet.xsl")));
transformer.transform(new SAXSource(new InputSource(new FileReader("Document.xml"))), new StreamResult(out));
}
}
It doesn’t work with a DOM source because the type annotations of all elements is stripped to xs:untyped by Saxon-SA, whether they have been validated or not.
SaxonSASample3.java
- Doesn’t require the document to point to the location of the schema.
- Uses a transformer handler.
import static java.lang.System.out;
import java.io.FileReader;
import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.ValidatorHandler;
import net.sf.saxon.FeatureKeys;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
public final class SaxonSASample3 {
public static void main(final String[] args) throws Exception {
final SAXParserFactory parserFactory = SAXParserFactory.newInstance();
parserFactory.setNamespaceAware(true);
final SAXParser parser = parserFactory.newSAXParser();
final XMLReader reader = parser.getXMLReader();
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); // ensure saxon9sa-jaxp.jar is in the classpath
final Schema schema = schemaFactory.newSchema();
final ValidatorHandler validatorHandler = schema.newValidatorHandler();
final SAXTransformerFactory transformerFactory = (SAXTransformerFactory) TransformerFactory.newInstance(); // ensure javax.xml.transform.TransformerFactory is set to com.saxonica.SchewaAwareTransformerFactory
transformerFactory.setAttribute(FeatureKeys.SCHEMA_VALIDATION_MODE, "strict");
final TransformerHandler transformerHandler = transformerFactory.newTransformerHandler(new StreamSource(new FileReader("Stylesheet.xsl")));
transformerHandler.setResult(new StreamResult(out));
validatorHandler.setContentHandler(transformerHandler);
reader.setContentHandler(validatorHandler);
reader.parse(new InputSource(new FileReader("Document.xml")));
}
}
SaxonSASample4.java
- Requires the document to point to the location of the schema.
- Uses a transformer handler.
import static java.lang.System.out;
import java.io.FileReader;
import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.ValidatorHandler;
import net.sf.saxon.FeatureKeys;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
public final class SaxonSASample4 {
public static void main(final String[] args) throws Exception {
final SAXParserFactory parserFactory = SAXParserFactory.newInstance();
parserFactory.setNamespaceAware(true);
final SAXParser parser = parserFactory.newSAXParser();
final XMLReader reader = parser.getXMLReader();
final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); // ensure saxon9sa-jaxp.jar is in the classpath
final Schema schema = schemaFactory.newSchema(new StreamSource(new FileReader("Schema.xsd")));
final ValidatorHandler validatorHandler = schema.newValidatorHandler();
final SAXTransformerFactory transformerFactory = (SAXTransformerFactory) TransformerFactory.newInstance(); // ensure javax.xml.transform.TransformerFactory is set to com.saxonica.SchemaAwareTransformerFactory
transformerFactory.setAttribute(FeatureKeys.SCHEMA_VALIDATION_MODE, "strict");
final TransformerHandler transformerHandler = transformerFactory.newTransformerHandler(new StreamSource(new FileReader("Stylesheet.xsl")));
transformerHandler.setResult(new StreamResult(out));
validatorHandler.setContentHandler(transformerHandler);
reader.setContentHandler(validatorHandler);
reader.parse(new InputSource(new FileReader("Document.xml")));
}
}
You can work around in both Saxon-SA and Saxon-B by using:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:template match="/Root">
<Root>
<Element>
<xsl:choose>
<xsl:when test="Element/@xsi:nil = xs:boolean('true')">0</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</Element>
</Root>
</xsl:template>
</xsl:stylesheet>
http://saxon.markmail.org/message/a6wbxegxr4wlfkb5?q=fn:nilled
http://www.w3.org/TR/xmlschema-2/#boolean
Thanks to Michael for the support.
XQuery 1.0 and XPath 2.0 Functions and Operators
Representations of null in XML Schema
Saxon-B Changes Between Progress Sonic ESB 7.5 and 7.6
net.sf.saxon.xpath.StandaloneContextwas replaced bynet.sf.saxon.sxpath.IndependentContext- The maximum number of prefixes per URI was raised from 256 to 1023. Beware the NamePoolLimitException.
fn Namespace in Saxon-B 8.4
The URI of the fn namespace in Saxon-B 8.4, used in Progress Sonic ESB 7.0 and 7.5, is http://www.w3.org/2005/04/xpath-functions, if you need to declare it explicitly.