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
Related
I am reading XML files that are validated via XSD files into XJC generated classes. That all works fine when I reference the XSD in the normal file system. Now I want to bundle the XSD into my JAR. That also works fine as long the XSD is standalone with the following code:
//Use the schema factory to get the schema
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
//Get XSD from JAR
InputStream schemaStream = getClass().getResourceAsStream("/schema/myschema.xsd");
Schema schema = sf.newSchema(new StreamSource(schemaStream));
//parse the XML file and fill the data model
Class<T> c = getXmlDataModelClass();
JAXBContext jaxbContext = JAXBContext.newInstance(c);
m_JaxbUnmarshaller = jaxbContext.createUnmarshaller();
//set the schema to be considered
m_JaxbUnmarshaller.setSchema(schema);
return (T)m_JaxbUnmarshaller.unmarshal(file);
Now the problem: if myschema.xsd includes another XSD:
<xs:include schemaLocation="BaseTypes.xsd"/>
The types in the included XSD are not found.
I also tried to pass an array of two StreamSource with both XSDs into sf.newSchema(), but that did not help.
The easiest is to use URLs, something like (not tested):
URL schemaURL = getClass().getResource("/schema/myschema.xsd");
Schema schema = sf.newSchema(schemaURL);
You'll get a jar:... URL and feed it to the schema factory. As long as included schemas reside in the same JAR, they should be resolved without problems.
For more advanced usage you may instantiate and provide a resource resolver to the schema factory:
sf.setResourceResolver(myResourceResolver);
The resource resolver resolves schemas into resources. You can use something like XMLCatalogResolver to rewrite schema URLs using catalog files, for instance. This would allow you to rewrite absolute URLs into local resources.
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.
I know that it is in general not allowed to access local Files (with java.io) within an EJB: nevertheless, I have an EJB which has to open an Excel File and edit it using the apache.poi library. If I do something like this:
#Stateless
public class MyEJB {
public void editExcel(){
...
InputStream in = MyEJB.class.getClassLoader().getResourceAsStream("/xls/ExcelFile.xls");
final Workbook generatedExcel = new XLSTransformer().transformXLS(in, beans);
...
} }
The filesystem structure:
MyEar.ear
--my-ejb.jar
---com
-----company
-------ejbs
----------MyEJB.class
---xls
-----ExcelFile.xls
In this case I will get an Instance of ZipFile$ZipFileInputStream (private inner class of ZipFileInputStream) and XLSTransformer will throw an IllegalArgumentException("Your InputStream was neither an OLE2 stream, nor an OOXML stream"), as it expects an InputStream representing ExcelFile.xls and gets instead a stream representing the whole my-ejb.jar.
My questions: do you know how to solve this situation? What is the best practice for accessing file within EJBs?
Thanks a lot!
I also had to return a modified XLS template out of a EE container once. Though I always look at such resources not as a part of the WAR/EAR deployment but as a configurable entity managed by customers.
So, one simple solution might be to save your template in a configuration directory, and provide it's path & name trough JNDI to your application.
BUT
You might also use JNDI for representing a more complex datatype representing an excel file, so your EJB code stays free of direct file operations.
You may find some pointers (for JBoss JNDI AS) here: http://middlewaremagic.com/jboss/?p=1690
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.
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.