Generating constants with XmlBeans - xsd

We are using XmlBeans 2.6.0 to generate classes from .xsd. A complex type has an attribute
<xs:attribute name="WEB" use="optional" fixed="2" type="xs:int"/>
An earlier version based on Apache CXF generated from this stuff
public static final int WEB = 2;
Is it possible somehow to get the same result using XmlBeans?
UPD Source generation is performed with xmlbeans-maven-plugin 2.3.3.
Thanks in advance.

Related

How do I change the case of XSD element name when generated as #XmlElement via xjc

I have a schema where element names are defined in PascalCase eg:
<xsd:element name="EmployeeName" minOccurs="0" maxOccurs="1">
But I would like this to generate as:
#XmlElement(name = "employeeName")
I know this sounds slightly strange but it will then allow me to use Jackson JAXB annotation support to have my JSON generated in camelCase.
Is this possible?
Yes, it is possible to change the XML element name to (nearly) whatever you want by way of the annotation directives.
In this example, "price" is renamed to "itemprice". Java is not case insensitive, so your camel casing will be honored.
//Example: Code fragment
public class USPrice {
#XmlElement(name="itemprice")
public java.math.BigDecimal price;
}
<!-- Example: Local XML Schema element -->
<xs:complexType name="USPrice"/>
<xs:sequence>
<xs:element name="itemprice" type="xs:decimal" minOccurs="0"/>
</sequence>
</xs:complexType>
This example comes from the JAXB javadocs.
Note that JAXB support has a few "how to use it" workflows, "XSD to generate supporting Java classes", and "Java classes to generate an XSD". I prefer the latter, but you may be using the former. If you are, then you need to alter your XSD to have camelCase element names there.
There is no "use my XSD to generate Java classes, but with some overrides" workflow. Perhaps that's where the confusion comes from. Likewise, there is no "Use Java class annotations to generated XSD documents, but with some overrides". What you specify is going to be what you get, name-wise.

How to map xs:any in EMF Ecore?

I have the following type in an xsd:
<xs:complexType name="VendorSpecificType">
<xs:sequence>
<xs:any namespace="##any" processContents="skip" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
I created this type in Ecore:
I tried to inject an xml containing the following tags:
<VendorSpecific>
<Vendor ID="1"/>
</VendorSpecific>
But it crashes
org.eclipse.m2m.atl.core.ATLCoreException: Error loading test.xml: org.eclipse.emf.ecore.xmi.FeatureNotFoundException: Feature 'Vendor' not found.
The code used to inject models in metamodels is tested and working.
Even this test.xml is loaded correctly if I remove the Vendor tag.
My question is how to map the xsd any to an ecore type so it can be loaded?
UPDATE:
After debugging, it seems that the code I use to inject the model into the ecore model is not complete: the extendedmetadata is always null
// Load in metamodel
IReferenceModel metamodel = modelFactory.newReferenceModel();
injector.inject(metamodel, metamodelPath);
model = modelFactory.newModel(metamodel);
injector.inject(model, modelPath);
How do I tell it to load the metadata?
I added the following line
((EMFModelFactory) modelFactory).getResourceSet().getLoadOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, Boolean.TRUE);
before injecting the metamodel.
It works now!

XSD Class generators: keeping track of element order

I got the following complex type within my XSD schema
<xs:complexType name="structure" mixed="true">
<xs:choice maxOccurs="unbounded">
<xs:element type="b" name="b" />
<xs:element type="a" name="a" />
</xs:choice>
</xs:complexType>
which allows me to state XML definitions like this:
<structure>
Hello <b>World</b>
Hello 2 <b>World 2</b>
<a>Hello3</a> <b>World3</b>
</structure>
Now I tried to generate XSD classes out of my schema, I tried both XSD.exe as well as XSD2Code. They both generate something like
class structure {
List<a> a;
List<b> b;
List<string> text;
}
My problem is, that I need to keep track in which order those elements where defined within the XML content of structure. Refering to the above example, I would like to know that the inner text "Hello" comes right before the first occurance of the b-element.
As this would obviously require a more specialized generator strategy, maybe I'm expecting too much, but: is there any XSD generator that can handle the object order or do I have to write my own classes?
Thank you in advance
I have never seen an XSD to code binding tool which would do what you need here, for sure not on the .NET platform - which you seem to imply as the target. This is one of those cases where roundtrip an XML is not possible, without loss of fidelity (deserialize, serialize then compare, it fails). Just for completeness, the /order option wouldn't work with xsd.exe, simply because in terms of the XSD you defined, there's no order really. It is, also, a limitation of what XSD can describe, which inevitably is reflected in tool implementations.

cvc-elt.1: Cannot find the declaration of element 'MyElement'

I'm trying to validate a really simple xml using xsd, but for some reason I get this error.
I'll really appreciate if someone can explain me why.
XML File
<?xml version="1.0" encoding="utf-8"?>
<MyElement>A</MyElement>
XSD File
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/Test"
xmlns:tns="http://www.example.org/Test"
elementFormDefault="qualified">
<simpleType name="MyType">
<restriction base="string"></restriction>
</simpleType>
<element name="MyElement" type="tns:MyType"></element>
</schema>
Your schema is for its target namespace http://www.example.org/Test so it defines an element with name MyElement in that target namespace http://www.example.org/Test. Your instance document however has an element with name MyElement in no namespace. That is why the validating parser tells you it can't find a declaration for that element, you haven't provided a schema for elements in no namespace.
You either need to change the schema to not use a target namespace at all or you need to change the instance to use e.g. <MyElement xmlns="http://www.example.org/Test">A</MyElement>.
After making the change suggested above by Martin, I was still getting the same error. I had to make an additional change to my parsing code. I was parsing the XML file via a DocumentBuilder as shown in the oracle docs:
https://docs.oracle.com/javase/7/docs/api/javax/xml/validation/package-summary.html
// parse an XML document into a DOM tree
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document document = parser.parse(new File("example.xml"));
The problem was that DocumentBuilder is not namespace aware by default. The following additional change resolved the issue:
// parse an XML document into a DOM tree
DocumentBuilderFactory dmfactory = DocumentBuilderFactory.newInstance();
dmfactory.setNamespaceAware(true);
DocumentBuilder parser = dmfactory.newDocumentBuilder();
Document document = parser.parse(new File("example.xml"));
I had this error for my XXX element and it was because my XSD was wrongly formatted according to javax.xml.bind v2.2.11 . I think it's using an older XSD format but I didn't bother to confirm.
My initial wrong XSD was alike the following:
<xs:element name="Document" type="Document"/>
...
<xs:complexType name="Document">
<xs:sequence>
<xs:element name="XXX" type="XXX_TYPE"/>
</xs:sequence>
</xs:complexType>
The good XSD format for my migration to succeed was the following:
<xs:element name="Document">
<xs:complexType>
<xs:sequence>
<xs:element ref="XXX"/>
</xs:sequence>
</xs:complexType>
</xs:element>
...
<xs:element name="XXX" type="XXX_TYPE"/>
And so on for every similar XSD nodes.
I got this same error working in Eclipse with Maven with the additional information
schema_reference.4: Failed to read schema document 'https://maven.apache.org/xsd/maven-4.0.0.xsd', because 1) could not find the document; 2) the document could not be read; 3) the root element of the document is not <xsd:schema>.
This was after copying in a new controller and it's interface from a Thymeleaf example. Honestly, no matter how careful I am I still am at a loss to understand how one is expected to figure this out. On a (lucky) guess I right clicked the project, clicked Maven and Update Project which cleared up the issue.
To expand upon the top answer. If you're using Java Web Services (JAX-WS) annotations to define your services, like in this example:
#WebService(..., targetNamespace = "http://bar.foo.com/")
Then make sure that your SOAP request has exactly the same namespace as defined in your annotation:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:foo="http://bar.foo.com/">
<soapenv:Header/>
<soapenv:Body>
<foo:someRequest>
...
</foo:someRequest>
</soapenv:Body>
</soapenv:Envelope>
The targetNamespace in your annotation and the xmlns:foo property in the XML request must match! Literally every character (including whitespace) must match. Also don't forget to put the / at the end as well (it's a very common mistake).

Using dom4j DOMDocument to feed validator.validate(DOMSource) fails in java 1.6 (xsi:noNamespaceSchemaLocation is not allowed), works in 1.5

Using dom4j DOMDocument to feed validator.validate(DOMSource) fails in java 1.6 (with xsi:noNamespaceSchemaLocation is not allowed to appear in root element), works in 1.5
I'm finding the following problem quite intractable (OK, that's an understatement) - any insights will be appreciated. Currently it seems like the best idea is to drop dom4j in favour of e.g. XOM (http://stackoverflow.com/questions/831865/what-java-xml-library-do-you-recommend-to-replace-dom4j).
I've been validating in memory XML created from dom4j 'new DOMDocument()' - but this will not work with Java 6.
The following call to validate(source) of a dom4j (1.6.1) DOMDocument derived DOMSource works with Java 1.5.x but fails with Java 1.6.x:
public void validate() throws Exception {
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
schemaFactory.setErrorHandler(null);
Schema schemaXSD = schemaFactory.newSchema(new URL(getSchemaURLString()));
Validator validator = schemaXSD.newValidator();
DOMSource source = new DOMSource(getDocument());
validator.validate(source);
}
getSchemaURLString() is also used to add the xsi:noNamespaceSchemaLocation attribute to the root node, i.e.:
xsi:noNamespaceSchemaLocation="http://localhost:8080/integration/xsd/fqlResponseSchema-2.0.xsd"
The exception follows:
Exception: org.xml.sax.SAXParseException: cvc-complex-type.3.2.2: Attribute 'xsi:noNamespaceSchemaLocation' is not allowed to appear in element 'specialfields'.;
complex-type.3.2.2: Attribute 'xsi:noNamespaceSchemaLocation' is not allowed to appear in element 'specialfields'.
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.createSAXParseException(ErrorHandlerWrapper.java:195)
at com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper.error(ErrorHandlerWrapper.java:131)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:384)
at com.sun.org.apache.xerces.internal.impl.XMLErrorReporter.reportError(XMLErrorReporter.java:318)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator$XSIErrorReporter.reportError(XMLSchemaValidator.java:417)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.reportSchemaError(XMLSchemaValidator.java:3182)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.processAttributes(XMLSchemaValidator.java:2659)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.handleStartElement(XMLSchemaValidator.java:2066)
at com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator.startElement(XMLSchemaValidator.java:705)
at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.beginNode(DOMValidatorHelper.java:273)
at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.validate(DOMValidatorHelper.java:240)
at com.sun.org.apache.xerces.internal.jaxp.validation.DOMValidatorHelper.validate(DOMValidatorHelper.java:186)
at com.sun.org.apache.xerces.internal.jaxp.validation.ValidatorImpl.validate(ValidatorImpl.java:104)
at javax.xml.validation.Validator.validate(Validator.java:127)
Here's the start of the XML - generated after disabling the call to validator.validate(source):
<?xml version="1.0" encoding="utf-8"?>
<meetings xsi:noNamespaceSchemaLocation="http://localhost:8080/integration/xsd/fqlResponseSchema-2.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
.............
</meetings>
And of the XSD:
<?xml version="1.0" encoding="utf-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
<xs:element name="meetings">
<xs:complexType>
<xs:choice>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="1" ref="summary" />
<xs:element minOccurs="0" maxOccurs="unbounded" ref="meeting" />
</xs:sequence>
<xs:element ref="error" />
</xs:choice>
</xs:complexType>
</xs:element>
<xs:element name="summary">
................
So my root element is being rejected because it contains a xsi:noNamespaceSchemaLocation attribute. And the schema itself does not specify that as a valid attribute of my root element?
At this point it seems to me that I need to give up on dom4j for this task and switch to one of the other solutions, for example as outlined here:
But I'd like to know what I've done wrong at any rate!
Thanks in advance.
I had the same issue, and I found the following documentation at
http://www.ibm.com/developerworks/xml/library/x-javaxmlvalidapi/index.html
Validate against a document-specified schema
Some documents specify the schema they expect to be validated against,
typically using xsi:noNamespaceSchemaLocation and/or
xsi:schemaLocation attributes like this:
<document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.example.com/document.xsd">
...
If you create a schema without specifying a URL, file, or source, then
the Java language creates one that looks in the document being
validated to find the schema it should use. For example:
SchemaFactory factory = SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
Schema schema = factory.newSchema();
However, normally this isn't what you want. Usually the document
consumer should choose the schema, not the document producer.
Furthermore, this approach works only for XSD. All other schema
languages require an explicitly specified schema location.
The reason seems to be that non-namespace aware JAXP SAXParser is being created and used (see Link).
And solution for different libs I found at www.edankert.com.

Resources