How to remove namespace definition from jackson Xml parsing - java

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.

Related

How to programmatically edit an xml schema file within eclipse plugin

I need to edit a xml-schema file (.xsd) within an eclipse plugin project (eclipse version is 4.2.2).
Right now, I'm able to read the xsd IFile in my eclipse project using org.apache.xerces.xs.XSModel in a way like this:
private XSModel readXSDModelFromResource(IFile xsdFile) throws CoreException, ClassNotFoundException, InstantiationException, IllegalAccessException, ClassCastException {
DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
XSImplementation xsImplementation = (XSImplementation) registry.getDOMImplementation("XS-Loader");
XSLoader schemaLoader = xsImplementation.createXSLoader(null);
LSInput input = new DOMInputImpl();
input.setBaseURI(xsdFile.getLocation().removeLastSegments(1).addTrailingSeparator().toOSString());
input.setSystemId(xsdFile.getFullPath().lastSegment());
input.setByteStream(xsdFile.getContents());
XSModel model = schemaLoader.load(input);
return model;
}
This is fine! My XSModel has the correct representation of the XML Schema, also following all the xsd:include tags.
But, I read here that
XSModel: a read-only interface that represents an XML Schema, which could be components from different namespaces.
And here that
XMLSchema is a lightweight Java object model that can be used to manipulate and generate XML schema representations. You can use it to read XML Schema (xsd) files into memory and analyze or modify them, or to create entirely new schemas from scratch.
Hence, since my needs are to add or delete elements, changing target namespaces and so on, my doubts are:
how can I manipulate the XSModel? What is (if exists) the related read-write object/library?
if i have to use Apache XMLSchema library, how can I import it into eclipse plugin project since the dependecies list for plugin.xml have nothing related to org.apache.ws.* package?
I'd like to avoid, if possile (I hope so :) ), the raw xml dom manipulation with DOM, SAX, DOM4J....
Thanks to all

XStream corrupting values on load and save

My team has recently inherited a codebase that utilizes XStream 1.4.7 to load and save XML for configuration settings which then de-/serializes them from/to custom POCOs. The problem that we're having is that some of the values are getting corrupted during reads or writes. It isn't consistently occurring either which makes it that much more unusual. In most cases, it works perfectly fine with the exact same XML and the exact same POCOs.
A very simplified example (I can't post the exact code and it's quite a bit more complex so I'm going for an easy way to explain what we're seeing) is given the XML:
<monitor>
<autostart>true</autostart>
<name>MYVALUE</name>
</monitor>
Mapped to a POCO:
public class MonitorEntry {
public Boolean autostart;
public String name;
}
Loaded with XStream:
XStream xStream = new XStream(new DomDriver());
xStream.alias("Monitor", MonitorEntry.class);
Monitor monitor = (Monitor)xStream.fromXML(myFile);
The value of name in the Monitor object is read in as arVALUE instead of MYVALUE. The garbage characters at the beginning are what throws things off. Even more strangely, if we change the value of the <autostart> element to false then the XML is mapped correctly and the garbage characters do not appear.
To add to the mystery, on our end we're only seeing the corruption on loading XML to objects, but on one particular customer system they are seeing corruption only when actually saving the XML from objects. In this case, it's exactly the opposite of the above scenario. Given the same POCO with name set to MYVALUE, the actual XML written to the XML file becomes:
<monitor>
<autostart>true</autostart>
<name>arVALUE</name>
</monitor>
Now for a string value such as name it isn't much of a functional issue as it's just a name that is then just spelled wrong but where this becomes a problem is when mapping the XML value to, for example, an enum and the mapping can't find the enum value.
An example being if there is an enum:
public enum Type { VALUE1, VALUE2 };
And the POCO is:
public class MonitorEntry {
public Boolean autostart;
public String name;
public Type type;
}
With the XML:
<monitor>
<autostart>true</autostart>
<name>MYNAME</name>
<type>VALUE2</type>
</monitor>
But the XML value is being read by XStream as erLUE2 then the XStream mapping won't be able to match the correct enum value and throws an exception such as:
No enum const class com.sample.MonitorEntry$Type.erLUE2
We tried updating to XStream 1.4.8 just to see if perhaps something had been fixed but the behavior persists. The codebase is set to compile to Java 1.6 but we've tried 1.6, 7, and 8 as runtimes just to see if it was a runtime bug or something else environmental.
Has anyone else seen similar issues or have any suggestions on what might cause this? I can further update my post to include more detail if necessary. We've used XStream quite a bit before but never had issues.
Edit: We are not currently using any custom converters in this codebase, only the built-in XStream converters.

Can JAXB store the class name in the XML so that the the deserialize code doesn't need knowledge of the class?

It seems the standard approach for deserializing JAXB XML is to specify the package name when creating the context. Then, JAXB looks up the class based on the root element:
JAXBContext jc = JAXBContext.newInstance("com.foo");
Unmarshaller u = jc.createUnmarshaller();
Object o = u.unmarshal(new StringReader("<?xml version="1.0" encoding="UTF-8" standalone="yes"?><MyJaxb>..."));
I'm looking for a more flexible approach where I don't have to specify the package name and could still deserialize any object. This would be as simple as JAXB storing the package in the XML, but I can't seem to find out how to do this. I can write the code to do it myself but that would be unpleasant. It would like JAXB to do it, if possible. BTW, I am not using schemas, just Annotations and marshal/unmarshal. Any ideas?
Actually you can not deserialize "any" object with pure JAXB. You have to specify either packages (where ObjectFactory.class will be sought) or list of classes like JAXBContext.newInstance(Class1.class, Class2.class, Class3.class); That's how jaxb works, it's a part of agreement.
If your tasks are wider that that, e.g. building java classes from arbitrary xml data structure - it's also possible, but you have to be a bit more concrete - what do you mean under "more flexible approach".
You should be able to add more than one package when you get the instance of the jaxbcontext object. You can add as many packages as you want like below.
JAXBContext jc = JAXBContext.newInstance("com.foo.package1:com.foo.package2" );
however, I am not sure how you are gonna use it if you deserialize it into an Object instance?
Are you not gonna use what you have just deserialized?
Also Unmarshaller is not a thread safe class if your application is a multithreaded one.

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.

How to easily load a XML-based Config File into a Java Class?

I've got a simple java class that looks something like this:
public class Skin implements Serializable {
public String scoreFontName = "TahomaBold";
...
public int scoreFontHeight = 20;
...
public int blockSize = 16;
...
public int[] nextBlockX = {205, 205, 205, 205};
...
public String backgroundFile = "back.bmp";
...
}
I'd like to read this information from a simple XML file that looks something like this:
<xml>
<skin>
<scoreFontName>"Tahoma Bold"</scoreFontName>
...
<scoreFontHeight>20</scoreFontHeight>
...
<blockSize>16</blockSize>
...
<nextBlockX>
<0>205</0>
<1>205</1>
<2>205</2>
<3>205</3>
<nextBlockX>
....
<backgroundFile>"back.bmp"</backgroundFile>
...
<skin>
</xml>
Is there an easy way to inject the information from the xml file directly into the variable names rather than having to parse it manually? I don't mind using an external library.
Any help is appreciated.
XStream is really great library for just this.
http://x-stream.github.io/
You can set up aliases for your class and even custom data formats to make the XML file more readable.
Alternatives to the already mentioned solutions (XStream and Apache Commons Digester) would be Java's own JAXB for a comparable general approach, or solutions more tailored towards configuration like Apache Commons Configuration or Java's Preferences API.
I would actually recommend Apache Digester, since if your classes are beans, it will just handle reading the XML into them.
You can also use Spring - although it may be a bit of overkill for one class if its for a mobile game!
I've recently started using Simple http://simple.sourceforge.net/ for XML to object mapping. It uses annotations within the class similarly to method I use in C# and is nice and clean.
You can also break up the file into multiple classes and loading saving is a simple one liner.
In your case the Class structure would look like.
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Root;
#Root (Name="skin")
public class Skin {
#Element(name="scoreFontName") // name param not needed if class field is the same as the xml (element) value
private String scoreFontName
#Element
private int scoreFontHeight
#Element
private int blockSize
#ElementArray
private int[] nextBlockX
#Element
private String backgroundFile
// getters
} 
Note one difference is that your array will be saved like this
<nextBlockX>
<int>205</int>
<int>205</int>
<int>205</int>
<int>205</int>
<nextBlockX>
But you you have the option of adding (entry="myName") to the annotation in which came the XML will be saved down like this
<nextBlockX>
<myName>205</myName>
<myName>205</myName>
<myName>205</myName>
<myName>205</myName>
<nextBlockX>
But the end result is the same once it's loaded into the array.
Use JAXB. It is included in the JDK starting with Java 1.6.

Categories