Using Saxon's DocumentBuilder with JAXB emits a warning about validation - java

I have an application that uses JAXB (Moxy) and Saxon for running XPath expressions. Everything works as expected, but Saxon's DocumentBuilder emits this warning:
XML Parser does not recognize the feature http://xml.org/sax/features/validation
Code:
Processor proc = new Processor(false);
DocumentBuilder builder = proc.newDocumentBuilder();
XdmNode doc = builder.build(new JAXBSource(jaxbContext, jaxbObject));//The warning occurs here
...
I think what's going on is JAXB is using a StaX parser and Saxon uses SAX. So when Saxon attempts to set the above property on the StaX parser, it fails.
Is there a way to prevent Saxon from setting that property when building the document or, at the very least, suppress that warning? I've tried setting a bunch of different properties on the Processor, but none of them worked. I don't need validation anyway since the document has already been validated and read into a JAXB object.
EDIT: I've been trying to override the errorListener on the Processor, DocumentBuilder, and the JAXBSource, but that message is not going through any of them.

I'll look into this a bit more closely, but the first thing to say is that JAXBSource extends SAXSource, and Saxon treats it exactly like it treats any other SAXSource. The warning in the JAXB documentation "Thus in general applications are strongly discouraged from accessing methods defined on SAXSource" is vacuous - applications (like Saxon) when they are defined to accept an object of class X, don't in general take any notice of advice given in the specifications of a subclass of X that they have never heard of.
The status of the property "http://xml.org/sax/features/validation" is a little unclear. IIRC the SAX specifications don't say that every XMLReader must recognize this property, but they do define it as the only way of requesting DTD expansion, and an XSLT processor needs DTD expansion to take place; if the XMLReader doesn't do DTD expansion then the transformation may fail in unpredictable ways, so a warning is justified.
The cleanest way of suppressing the warning is probably to supply an XMLReader that does recognise this property, and delegate from there to an XMLReader that doesn't recognise it.

private class SaxonLogger extends StandardLogger {
#Override
public void warning(String message) {
if(!message.contains("http://xml.org/sax/features/validation")) {
System.err.println(message);
}
}
}
...
proc.getUnderlyingConfiguration().setLogger(logger);
This will at least suppress those pesky messages. However, I would still like to find a better solution.

Related

Hi, I'm facing a blocker in a SonarQube violation - Disable access to external entities in XML parsing

Tried with the fix given in sonarqube.
*TransformerFactory tfactory = TransformerFactory.newInstance();
tfactory.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
tfactory.setAttribute(javax.xml.XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
return tfactory;*
But I'm facing a runtime exception on setAttribute:
"java.lang.IllegalArgumentException: Unknown configuration property http://javax.xml.XMLConstants/property/accessExternalDTD"
This seems to be because of a bug in the version of saxon jar im using [9.7] . And its working fine on saxon 10.3 . Please refer https://saxonica.plan.io/issues/4729 for this bug.
Below are my questions:
Is there any way to make it work on my existing saxon version (without upgrading it to 10.x). Tried using transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true) but sonarqube is not satisfied as it expects above fix.
If upgrading to 10.x is the only way, then below is the challenge im facing:
I'm overriding a method from TraceListener for some business logics. But the method signature
got changed on latest version like below:
Class - net.sf.saxon.lib.TraceListener
Saxon 9.7 -> public void enter(InstructionInfo instruction, XPathContext context)
Saxon 10.x -> public void enter(Traceable instruction,
java.util.Map<java.lang.String,java.lang.Object> properties, XPathContext context)
My current Code:
*#Override
public void enter(InstructionInfo instruction, XPathContext context) {
int data = instruction.getConstructType();
if ((data == 155) || (data == 200)) {
.......logic......
}
}*
My new code will be :
*#Override
public void enter(Traceable instruction,
java.util.Map<java.lang.String,java.lang.Object> properties, XPathContext context){
--> what to use here for getConstructType()
if ((data == 155) || (data == 200)) {
.......logic......
}
}*
So the problem is 10.x jar doesn't have getConstructType() method in its Traceable class or InstructionInfo class. How do I use getConstructType() in 10.x version?
P.S : It will be very helpful if the 1st question gets answered i.e) if I can be able to resolve with my current version of jar as new version requires testing of all the functionalities throughout the project :( Hope someone can help me, thanks in advance.
First point: to be a little argumentative, it is NOT a bug in Saxon 9.7. The Javadoc for TransformerFactory (in Java 8) says "All implementations that implement JAXP 1.5 or newer are required to support the XMLConstants.ACCESS_EXTERNAL_DTD and XMLConstants.ACCESS_EXTERNAL_STYLESHEET properties." but Saxon 9.7 never claimed to implement JAXP 1.5, it only claimed to implement JAXP 1.3.
Saying "I want to stay on an old release of Saxon but I can't, because I want a version that supports a new feature of JAXP" is very understandable, but not actually very logical.
One solution to this is to add your own implementation of the TransformerFactory API, which intercepts the attempt to set this property and doesn't pass it on to Saxon.
Note that this property is in the wrong place anyway. DTD processing is the responsibility of the XML parser, not the XSLT processor. The specification doesn't make it clear exactly what effect it's supposed to have. If the XSLT processor instantiates the XML parser, it seems reasonable that it should pass the property on, but what should it do if it's not accepted? And should it pass it on at all if the XML parser is created by the user application rather than by the XSLT processor? Generally it's a very frustrating exercise trying to implement rules like this in the JAXP specification, which are often very fuzzily specified.
I would encourage you generally to try to keep abreast of new Saxon releases to avoid hitting problems which have already been solved. Yes, it's true that we occasionally revise the design of some of the "system programming" interfaces such as the TraceListener interface. The 10.3 version of this interface replaces InstructionInfo with Traceable, and to find out what kind of Traceable is involved, you should use instanceof.
When we do make changes, we often introduce a new API in one major version and drop the old API in the following version. If you jump forward three major releases in one go (9.7 to 10, skipping 9.8 and 9.9) then you're not able to take advantage of these transition aids.

How to remove namespace definition from jackson Xml parsing

I'm using Jackson data format for serializing Pojos as XML.
It is working fine but I would like to remove the namespace definition:
#JacksonXmlRootElement(localName="simple_something")
public class Simple {
public int x = 1;
public int y = 2;
}
I do:
ObjectMapper xmlMapper = new XmlMapper();
String xml = xmlMapper.writeValueAsString(new Simple());
I get:
<simple_something xmlns="">
<x>1</x>
<y>2</y>
</simple_something>
but I would like to remove the xmlns=""
and that it looks like
<simple_something>
<x>1</x>
<y>2</y>
</simple_something>
Any ideas?
Make sure to use Woodstox Stax implementation, and not Stax implementation Oracle bundles with JDK. This is usually done by adding Maven dependency to explicitly include woodstox jar.
This is explained on XML module README at https://github.com/FasterXML/jackson-dataformat-xml/
Oracle's implemention adds that declaration in namespace-repairing mode for some reason. It is also slower and has more bugs, so there's not much reason to rely on it, unless you really want to minimize external dependencies.
Also note that that namespace declaration is completely benign, so while unnecessary it is legal XML. So while it is eyesore all xml tools should work just fine with such extra declarations.

How to create multiple xml request by only changing one field?

I need help to find the approach of how to create xml multiple times while I will be changing only two fields everytime and rest of the fields would be same as now. Please tell me the way to do it in java?
This is the sample xml below:
I would be changing the value of <Id> and <Originator>
<TransactionBlk>
<Id>NIK</Id>
<CorrelationId />
<Originator>NIK</Originator>
<Service>GetIns</Service>
<VersionNbr>1</VersionNbr>
<VersionNbrMin>0</VersionNbrMin>
<MsgNm>Req</MsgNm>
<MsgFormatCd>XML</MsgFormatCd>
</TransactionBlk>
You can crate one class contain all this parameter as class variable, create getter and setter method. Create object of class set value by using setter method.
You can use JAXB API's class to convert your java object into XML format.
The JAXBContext class provides the client's entry point to the JAXB API.
It provides an abstraction for managing the XML/Java binding information
necessary to implement the JAXB binding framework operations: unmarshal,
marshal and validate.
Here is Doc reference for convert your Java object into XML.
Here are tutorial for same Tutorial Link
Sample Code :
#XmlRootElement(name="TransactionBlk_REQ",namespace="http://TransactionBlk.com")
#XmlAccessorType(XmlAccessType.FIELD)
public class TransactionBlk
{
#XmlElement(name = "Id")
private String id;
#XmlElement(name = "Originator")
private String Originator;
//Your getter and setter method.
}
TransactionBlk bean = new TransactionBlk();
//Set your parameter value here
StringWriter responseWriter = new StringWriter();
JAXBContext jaxbContext = JAXBContext.newInstance(TransactionBlk.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.marshal(bean, responseWriter);
String xmlStr = responseWriter!=null?responseWriter.toString():null;
You can use XSLT to transform XML.
If all you're doing is printing a "boilerplate" document with changes in those two values, a, you could use the DPH (Desperate Perl Hacker) approach: simply assemble it as text, pausing to print the values at the appropriate places. To be safe, you should pre-scan the values to make sure they don't contain the <, >, or & characters and escape those if you find them.
For something more complex, or if you want to start learning how to do it "properly", look at the standard XML APIs for Java: DOM (the Document Object Model, an in-memory tree model of a document), SAX (an event-stream view of a document), and JAXP (tools to take an XML document and parse it into DOM or SAX so you can read it, and to take DOM or SAX and write those out as XML syntax). JAXP also provides standard APIs for invoking XPath to search a document and XSLT to apply a stylesheet to a document, so taken together these cover a huge percentage of the basic operations on XML.
You might want to look at some tutorials on using Java to manipulate XML. I'm certainly biased, not least because they published one of my articles, but in my experience IBM's DeveloperWorks website (https://www.ibm.com/developerworks/xml/) has had better-than-average material for learning about XML and other standards.

Is there a way to create a Schema object using an XML schema consisting of circular dependencies?

I've been given a schema that contains two .xsd files that include each other (a.xsd includes b.xsd, b.xsd includes a.xsd). When I run them through my code to return a Schema object, I get an out of memory exception.
My code is as follows:
protected Schema createSchema(String fileName) throws Exception {
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
factory.setResourceResolver(resourceResolver);
Resource schemaResource = resourceLoader.getResource(fileName);
StreamSource streamSource = new StreamSource(schemaResource.getInputStream());
Schema schema = factory.newSchema(streamSource);
return schema;
}
Correct me if I'm wrong, factory.newSchema(streamSource) is using the includes, along with imports, to load the sources into memory. And since these two xsd's include each other, they are loaded over and over again, filling up memory space. Is there a way to break out of this loop and load the rest of the schema WITHOUT changing the schema design?
I was under the impression that most schema processors could handle circular includes: they are never necessary, but they should be harmless. (However, the spec is far from clear on this point.)
Since you are using a resourceResolver of some kind, it's possible that the schema processor isn't recognizing that the URI of an include points back to a document it has already seen.
On the other hand, using a resourceResolver might be a way to eliminate the circularities by returning nothing (or an empty xs:schema) when a schema document is visited the second and subsequent times.
You don't actually say which schema processor you are using: there are at least two processors that implement the JAXP API which you are using here - more than that if you count different forks of Xerces.

How should I use Stax2 Validation API against a W3 Schema

I am using com.ctc.wstx.stax.WstxOutputFactory to generate XML.
I am running wstx-asl-3.2.4
I need to start validating the generated XML against a W3 Schema.
When I create an instance of org.codehaus.stax2.validation.XMLValidationSchemaFactory like this
private final static XMLValidationSchemaFactory xsdFact=
XMLValidationSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA);
I get the error
javax.xml.stream.FactoryConfigurationError: No XMLValidationSchemaFactory implementation class specified or accessible (via system property 'org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c', or service definition under 'META-INF/services/org.codehaus.stax2.validation.XMLValidationSchemaFactory.w3c')
at org.codehaus.stax2.validation.XMLValidationSchemaFactory.newInstance(XMLValidationSchemaFactory.java:208)
at org.codehaus.stax2.validation.XMLValidationSchemaFactory.newInstance(XMLValidationSchemaFactory.java:98)
I can see that woodstox is bundled with a DTD parser only.
I found this article
which contains the unhelpful instruction
Get an instance of XMLValidationSchemaFactory that knows how to parse schemas of the type you need (RelaxNG == rng for this example).
I have been looking at the Sun Multi-Schema XML Validator which is supposed to contain the bits necessary to bolt on to the XMLSchemaValidation factory.
It looks like I might be able to use com.sun.msv.reader.xmlschema.XMLSchemaReader
to write my own instance of XMLValidationSchemaFactory and get it to work this way.
My question is; do I really have to do this, or is there a pre-existing w3c schema factory that I have failed to find?
Perhaps it would be simpler just to validate the XML after I have generated it.
What are the views on this ?
I've upgraded to Woodstox 4.0.8, W3CSchemaFactory comes bundled and its all good.

Categories