Validate XML against XSD with custom validations - java

Normally there is a standard way how to validate XML against XSD schema in Java, but I need to have more sophisticated validation, for example validation for Zip Postal Code which ensure that such ZIP really exists. Therefore I need some kind of customizable Validator to which I will define rule like: (sorry for triviality)
if( validationType.equals("ZipPostalCode") {
com.fuu.validations.Address.zipPostalCode( innerText );
}
What is the most straightforward way to achieve such custom validations in Java with XSD and some customisable validator library?

If you use Saxon as your schema processor, then you can use XSD 1.1 assertions that invoke external Java methods:
<xs:simpleType name="zipCode" base="xs:string">
<xs:assertion test="ext:isValidZipCode($value)" xmlns:ext="java:com.fuu.validations.Address"/>
</xs:simpleType>

Related

Generate wrapper for the Jaxb generated ObjectFactory methods nillable=true, minOccurs=0

I am using JAXB, I have xsd files which I cannot modify which has elements with
minOccurs="0" nillable="true"
Which results that in the generated ObjectFactory class I have a lot of code like:
JAXBElement<SomeObject>
Then the code, that I have to write to both marshall and unmarshall is boilerplate and ugly.
Is there a way to generate somehow automaticaly another layer of abstraction so that I would have some other ObjectFactory class as well, but it would not operate on JAXBElement but instead would have it wrapped in some methods? Like it is when in the binding.xjb you specify the following:
<jaxb:globalBindings localScoping="toplevel" generateElementProperty="false">
which is unfortunately not an option for me.

Adding annotations to JAXB-generated classes which depend on information in XSD

I have a WSDL + XSD that needs to be turned into Java classes. That's pretty simple - wsimport will handle that without issue. However, I also need to be able to add annotations to the generated classes, and those annotations need to contain information that is contained in the XSD (in particular, they need to reference the xsd:maxLength or xsd:length properties).
Why? Because I plan to transform them into a flat file afterwards, using Bindy. For reference, I know that I can use Annox to add custom annotations to the generated classes, but as far as I'm aware, that would require that either all annotations are identical, with all parameters being identical, or specifying annotations for each element individually, with no way to specify the annotation once along with some way (e.g. xpath) of specifying that the value of one of the parameters should be different for each element.
That is, given a schema extract like
<xsd:element name="smapleRequest">
<xsd:sequence>
<xsd:element name="ELEMENT_ONE">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:length value="3" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
<xsd:element name="ELEMENT_TWO">
<xsd:simpleType>
<xsd:restriction base="xsd:string">
<xsd:maxLength value="8" />
</xsd:restriction>
</xsd:simpleType>
</xsd:element>
</xsd:sequence>
</xsd:element>
I would like to see classes that look this:
.
.
.
#FixedLengthRecord
public class SampleRequest {
#XmlElement(name = "ELEMENT_ONE", required = true)
#DataField(pos = 1, length=3)
protected String elementOne;
#XmlElement(name = "ELEMENT_TWO", required = true)
#DataField(pos = 4, length=8)
protected String elementTwo;
.
.
.
}
Ideally, I would like to be able to do this without having to duplicate all the information from the XSD into the JAXB Binding File. I mean, I could, but with potentially hundreds of elements per web service method, and dozens of methods, that would get very, very old very, very fast. At that point, I would probably have to use another tool to generate the XSD and JAXB binding file(s) from the COBOL!
So, does anyone know if this is possible? Have I just missed something in Annox? Or am I just asking for too much here?
You have few options: XJC plugins is one route and Annox looks interesting. But I'm no expert so I'll let others explore it with you.
The other route I would suggest you consider, if you get stuck with the first one, is to post-process your generated JAXB sources via annotation processing (formerly the apt tool, now part of the javac tool) to access the XSD and append your annotations on the fly. Not sure that would work for all your cases, but in the example you gave, the JAXB-generated annotations should be enough to construct an XPath expression to read the corresponding XML element type characteristics. Assuming your needs are essentially around the field length, that should be few use cases and XPath expressions.
To automatically add XJsr303Annotations annotations you could use xjc plugin https://github.com/krasa/krasa-jaxb-tools
Plese see my answer Generation of XSD restrictions in a schema generated from Java JAXB annotated classes for details.

Spring JAXB - Unmarshalling an XML document with schema validation

I am trying to work out how to unmarshall and XML document to a Java document.
The top of the xml document looks like this
<xs:myData xmlns:xs="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com example.xsd ">
There is a schema file whose top section looks like this:
<schema targetNamespace="http://www.example.com"
elementFormDefault="qualified"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xs="http://www.example.com">
I would like to unmarshall the xml document using Spring/JaxB and eventually convert it to a JPA object. I am not sure how to go about so i looked for examples on google and came up with this http://thoughtforge.net/610/marshalling-xml-with-spring-ws-and-jaxb/
I understand most of it except how or where the schema is used.
I have seen other examples where the schema is explicitly specified, i.e.
SchemaFactory schemaFac = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema sysConfigSchema = schemaFac.newSchema(
new File("example.xsd"));
unmarshaller.setSchema(sysConfigSchema);
RootElement root = (RootElement)unmarshaller.unmarshal(
new File("example1.xml"));
How is the schema shown in the first link used to validate the xml document?
Are there any disadvantages to using Spring's jaxb2Marshaller as opposed to direct use of JAXB?
What is the effect of having the namespace next to the XmlElement annotation? (See the Person class)
I would appreciate any more examples showing Spring/REST with unmarshalling with schema validation.
Thanks
As far as I know JAXB does not parse xsi attribute to dereference XSD, load it and use for validation. Perhaps that was done to disable automatic validation, otherwise it would be problematic to switch it off :)
Spring Jaxb2Marshaller was obviously added to implement the same interface org.springframework.oxm.Marshaller (which is implemented also by CastorMarshaller, JibxMarshaller, ...). It is very powerful and allows you to tune JAXBContext in very flexible way (I can't imagine the scenario when provided API is not enough). From pattern point of new Jaxb2Marshaller is a builder, so it does not add anything to core JAXB functionality. But there are some evident advantages. For example, schema loading is very simple. In the article the Spring context refers the person.xsd (<property name="schema" value="classpath:schema/person.xsd"/>) which one need to put into resources explicitly. Then JAXB marshaller/unmarshaller will use this schema to validate XML when XML is generated/loaded.
#XmlElement(..., namepsace="xxx") will automatically generate this XML element with a specified namespace. It's rare case if somebody does not use namespaces. I would say writing XSD without namespaces is not normal, as you want to avoid the element name collision.
Using JAXB with RestTemplate is very simple. You need to be sure that JAXB runtime is in your classpath (JDK 6 already has it) and your bean is annotated with #XmlRootElement. Then just use Person person = restTemplate.getForObject(restServiceUrl, Person.class),

How to detect required XML attributes?

I have an XML content without defined attributes, like this:
<rootElement>
<subElement1/>
</rootElement>
I want to populate this XML content with required attributes defined in XML Schema (XSD) for this XML.
For example, according to XSD subElement1 has required attribute 'id'.
What is the best way (for Java processing) to detect that and add such attributes to XML?
We need to add required attributes and set appropriate values for them.
As a result for example above we need to have the following XML:
<rootElement>
<subElement1 id="some-value"/>
</rootElement>
In the XML schema definition, i.e. XSD file, attributes are optional by default. To make an attribute required, you have to define:
<xs:attribute name="surname" type="xs:string" use="required"/>
You will find a very good introduction on XML and XML Schema Definitions, i.e. XSD, on W3 Schools.
In Java the equivalent of defining a XML schema is using JAXB, i.e. Java API for XML Binding that is included into Java SE. There you would define, e.g.
#XmlRootElement
public class Person { public #XmlAttribute(required=true) String surname; }
Hope this could clarify your question.
I would suggest you to use JAXB for that. Search the Internet for tutorials.
Steps to proceed further with JAXB,
Generate Java files using JAXB by providing the schema
Unmarshal your XML to generated Java classes (beans). Don't do validation or set validation handler here.
Populate those classes with appropriate values. required elements can be found using annotation look up. JAXB annotation for element would look like something, #XmlElement(name = "ElementName", required = true). And an attribute annotation would be something similar to this, #XmlAttribute(required = true)
Marshal your bean back to XML. You can validate your bean using ValidationHandler, while marshalling. Below is the sample code snippet,
marshller = JAXBContext.newInstance(pkgOrClassName).createUnmarshaller();
marshller.setSchema(getSchema(xsd)); // skip this line for unmarshaller
marshller.setEventHandler(new ValidationHandler()); // skip this line for unmarshaller
Use a DOM parser.Has methods to traverse XML trees, access, insert, and delete nodes
I have had the same idea of Cris but I think that with this validator you don't have information about the point in which you have had the error.
I think that you have to create or extend your own validator.

XML/RDF to Java Objects with XSD

So here's the scenario...I have an XSD file describing all the objects that I need. I can create the objects in Java using JAXB no problem. I have an XML/RDF file that I need to parse into those objects.
What is the EASIEST way to do this?
I have been looking into Jena and have played around with it, but can't see how to easily map the XML/RDF file to the XSD objects that were generated. Here is a snippet of the XSD file as well as the XML/RDF file:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:a="http://langdale.com.au/2005/Message#"
xmlns:sawsdl="http://www.w3.org/ns/sawsdl"
targetNamespace="http://iec.ch/TC57/2007/profile#"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
xmlns="http://langdale.com.au/2005/Message#"
xmlns:m="http://iec.ch/TC57/2007/profile#">
<xs:annotation/>
<xs:element name="Profile" type="m:Profile"/>
<xs:complexType name="Profile">
<xs:sequence>
<xs:element name="Breaker" type="m:Breaker" minOccurs="0" maxOccurs="unbounded"/>
And the XML/RDF:
<!-- CIM XML Output For switch783:(295854688) -->
<cim:Switch rdf:ID="Switch_295854688">
<cim:IdentifiedObject.mRID>Switch_295854688</cim:IdentifiedObject.mRID>
<cim:IdentifiedObject.aliasName>Switch_295854688</cim:IdentifiedObject.aliasName>
<cim:ConductingEquipment.phases
rdf:resource="http://iec.ch/TC57/2009/CIM-schema-cim14#PhaseCode.ABC" />
<cim:Switch.circuit2>0001406</cim:Switch.circuit2>
<cim:Equipment.Line rdf:resource="#Line_0001406" />
You could iterate through the RDF statements and populate your JAXB beans via a Bean population utility like BeanUtils.
Iterate the statements in such a form that statements with the same subject are processed in a group. The rdf:type statements define which Class to instantiate and the rest can be probably mapped to properties of the created beans.
If you are familiar with Java reflection then this is probably quite straightforward.
What isn't clear from your post is any mapping between the XSD components and the particular resource data you have in RDF (or schema thereof, such as RDFS or OWL, or both).
If you understand this mapping, then given you have a JAXB implementation to create Java objects already (with a view to populate them with the data represented as RDF) and a Jena implementation to parse the RDF/XML in Java, then I suggest that you can implement a Java 'bridge' - effectively custom code that queries the Jena model of the RDF data to map it into new objects of the classes as generated by JAXB, which can then be marshaled to the required XML.
If you'd rather not write any Java code at all to do this, you could write some XSLT or XQuery to transform your RDF/XML directly into the required XML, but this sounds like it will be more work than the aforementioned option given what you've got already.
Do the Resource/Subject/etc objects not have any methods for converting to DOM Element?
Alternatively (not the neatest solution for sure) what about serializing to string and reading the string then using the JAXB-created (from XSD) objects' setter methods??

Categories

Resources