<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:foo="http://www.foobar.com/foo">
<xs:element name="movies">
<xs:complexType>
<xs:sequence>
<xs:element name="movie" type="xs:string"
foo:bar="somevalue"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
When I inspect the element name I don't see the attribute
foo:bar="somevalue" among its attributes. Anyone know how to "see" it? I
can provide a lot more details if needed. Right now my code depends on a
very old, modified version of xerces that is able to see attributes in
other namespaces (if that is the correct way to describe the attribute
foo:bar?).
- Eric (WP)
> I'm using Xerces
> to create an XSModel and from a schema and from this XSModel I obtain an
> element declaration map (basically to get the root element from which I
> can get all sub-elements).
>
[...]
> <xs:element name="movie" type="xs:string" foo:bar="somevalue"/>
[...]
>
> When I inspect the element name I don't see the attribute
> foo:bar="somevalue" among its attributes. Anyone know how to "see" it? I
> can provide a lot more details if needed. Right now my code depends on a
> very old, modified version of xerces that is able to see attributes in
> other namespaces (if that is the correct way to describe the attribute
> foo:bar?).
I'm not 100% sure whether this is your case but enhancements to the
XML Schema annotation support was first introduced in Xerces 2.8.0
<http://xerces.apache.org/xerces2-j/releases.html>:
> All of the schema component interfaces in the XML Schema API now
> have a getAnnotations() method which returns a list of
> XSAnnotations. This includes annotations on particles and attribute
> uses which were previously "lost".
If you notice in the original XML Schema specification particle
components <http://www.w3.org/TR/xmlschema-1/#Particle_details>
don't have annotations.
In any case you would get better support on the Xerces-J Users
mailing list:
http://mail-archives.apache.org/mod_mbox/xerces-j-users/
--
Stanimir
Thanks for your suggestions. I wrote this complete test program, it uses
Xerces-J 2.9.1:
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.xerces.xs.XSComplexTypeDefinition;
import org.apache.xerces.xs.XSConstants;
import org.apache.xerces.xs.XSElementDeclaration;
import org.apache.xerces.xs.XSImplementation;
import org.apache.xerces.xs.XSLoader;
import org.apache.xerces.xs.XSModel;
import org.apache.xerces.xs.XSModelGroup;
import org.apache.xerces.xs.XSNamedMap;
import org.apache.xerces.xs.XSObjectList;
import org.apache.xerces.xs.XSParticle;
import org.apache.xerces.xs.XSTerm;
import org.apache.xerces.xs.XSTypeDefinition;
import org.apache.xerces.impl.xs.XSImplementationImpl;
public class ParseXMLSchema {
public static void main(String[] args) {
ParseXMLSchema instance = new ParseXMLSchema();
instance.parseXMLSchema(new File("test-1.xsd"));
}
private void parseXMLSchema(final File f) {
parseXMLSchema(f.getAbsolutePath());
}
private void parseXMLSchema(final String schemaFileName) {
XSImplementation xsImplementation = new XSImplementationImpl();
XSLoader xsLoader = xsImplementation.createXSLoader(null); // or
new XSLoaderImpl();
XSModel xsModel = xsLoader.loadURI(schemaFileName);
XSNamedMap elementMap =
xsModel.getComponents(XSConstants.ELEMENT_DECLARATION);
XSElementDeclaration topElementDecl =
(XSElementDeclaration)elementMap.item(0);
process(topElementDecl);
}
private void process(final XSElementDeclaration elementDecl) {
if (elementDecl == null) {
System.err.println("elementDecl is null.");
return;
}
XSComplexTypeDefinition typeDef =
(XSComplexTypeDefinition)elementDecl.getTypeDefinition();
System.out.print("Complex element: " + elementDecl.getName());
XSObjectList attributeUsesList = typeDef.getAttributeUses();
if (attributeUsesList.getLength() == 0) {
System.out.print(", no attributes");
}
else {
for (int i = 0; i < attributeUsesList.getLength(); ++i) {
System.out.println("Attribute " + i + 1 + ": " +
attributeUsesList.item(i).getName());
}
}
List<XSElementDeclaration> ces = new
ArrayList<XSElementDeclaration>();
XSModelGroup modelGroup =
(XSModelGroup)typeDef.getParticle().getTerm();
XSObjectList particles = modelGroup.getParticles();
for (int i = 0; i < particles.getLength(); ++i) {
XSParticle particle = (XSParticle)particles.item(i);
XSTerm term = particle.getTerm();
XSObjectList annotations = particle.getAnnotations();
printAnnotations(annotations);
if (term instanceof XSElementDeclaration) {
XSElementDeclaration newElement = (XSElementDeclaration)term;
if (newElement.getTypeDefinition().getTypeCategory() ==
XSTypeDefinition.SIMPLE_TYPE) {
System.out.print("Simple element: " + newElement.getName());
XSObjectList simpleElementAnnotations =
newElement.getAnnotations();
printAnnotations(simpleElementAnnotations);
}
else if (newElement.getTypeDefinition().getTypeCategory()
== XSTypeDefinition.COMPLEX_TYPE) {
ces.add(newElement);
}
else {
System.out.println("Other type.");
}
}
else {
System.out.println("Something else.");
}
}
for (XSElementDeclaration e : ces) {
process(e);
}
}
private void printAnnotations(final XSObjectList annotations) {
if (annotations.getLength() == 0) {
System.out.println(", no annotations");
}
else {
System.out.println(", " + annotations.getLength() + "
annotations");
}
}
}
Sorry for the length, but I wanted it to be complete. For the following
test schema:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="myns" xmlns="myns"
elementFormDefault="qualified"
xmlns:foo="http://www.foobarbaz.com/foo">
<xs:element name="movies">
<xs:complexType>
<xs:sequence>
<xs:element name="movie" type="xs:string"
maxOccurs="unbounded" foo:bar="baz"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
it produces the following output:
Complex element: movies, no attributes, no annotations
Simple element: movie, no annotations
As you can see, I am unable to detect foo:bar="baz" on the element
movie. Any ideas what I'm missing in my code?
>
> In any case you would get better support on the Xerces-J Users mailing
> list:
>
> http://mail-archives.apache.org/mod_mbox/xerces-j-users/
>
I posted there over a week ago without a single reply and activity on
that list is very low in general so please forgive me. :( But I will
post their again with the complete example program I used in this post.
- Eric (WP)
Lookin at it a bit further and trying it out I think this is more
what you're after
<http://xerces.apache.org/xerces2-j/features.html#generate-synthetic-annotations>:
> Enable generation of synthetic annotations. A synthetic annotation
> will be generated when a schema component has non-schema attributes
> but no child annotation.
>
> Since: Xerces-J 2.7.0
Given your original example schema packaged as "example.xsd" with
the following class, appears to work for me using Xerces 2.9.1 (but
I guess 2.7.0 should be fine, too):
-----XSModelTest.java
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;
import javax.xml.transform.stream.StreamResult;
import org.apache.xerces.xs.XSAnnotation;
import org.apache.xerces.xs.XSComplexTypeDefinition;
import org.apache.xerces.xs.XSElementDeclaration;
import org.apache.xerces.xs.XSImplementation;
import org.apache.xerces.xs.XSLoader;
import org.apache.xerces.xs.XSModel;
import org.apache.xerces.xs.XSModelGroup;
import org.apache.xerces.xs.XSObjectList;
import org.apache.xerces.xs.XSParticle;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.bootstrap.DOMImplementationRegistry;
public class XSModelTest {
private static SAXTransformerFactory transformerFactory =
(SAXTransformerFactory) TransformerFactory.newInstance();
public static void main(String[] args) throws Exception {
DOMImplementationRegistry registry =
DOMImplementationRegistry.newInstance();
XSImplementation impl = (XSImplementation)
registry.getDOMImplementation("XS-Loader");
XSLoader schemaLoader = impl.createXSLoader(null);
DOMConfiguration config = schemaLoader.getConfig();
config.setParameter("http://apache.org/xml/features/"
+ "generate-synthetic-annotations",
Boolean.TRUE);
XSModel schema = schemaLoader.loadURI(XSModelTest.class
.getResource("example.xsd").toExternalForm());
XSElementDeclaration elemDecl =
schema.getElementDeclaration("movies", null);
XSComplexTypeDefinition typeDef = (XSComplexTypeDefinition)
elemDecl.getTypeDefinition();
XSParticle contentModelParticle = typeDef.getParticle();
printAnnotations(contentModelParticle.getAnnotations());
XSModelGroup contentModelGroup = (XSModelGroup)
contentModelParticle.getTerm();
XSParticle elemParticle = (XSParticle)
contentModelGroup.getParticles().item(0);
System.out.println("--- Particle annotations:");
printAnnotations(elemParticle.getAnnotations());
System.out.println("--- Element declaration annotations:");
elemDecl = (XSElementDeclaration) elemParticle.getTerm();
printAnnotations(elemDecl.getAnnotations());
System.out.println("--- End.");
}
static void printAnnotations(XSObjectList annotations)
throws Exception {
for (int i = 0, len = annotations.getLength();
i < len; i++) {
TransformerHandler handler =
transformerFactory.newTransformerHandler();
Transformer transformer = handler.getTransformer();
transformer.setOutputProperty(OutputKeys
.OMIT_XML_DECLARATION, "yes");
transformer.setOutputProperty(OutputKeys
.INDENT, "yes");
handler.setResult(new StreamResult(System.out));
((XSAnnotation) annotations.item(i))
.writeAnnotation(handler,
XSAnnotation.SAX_CONTENTHANDLER);
}
}
}
-----XSModelTest.java--
--
Stanimir
Now I see your previous post on the Xerces mailing list. I'm
subscribed to the list but I'm not following it very closely as I've
changed job recently and don't work with "hard-core" :-) XML
applications currently. See if my second reply to this thread will
help.
--
Stanimir
Ah! :) And I'm on my first job where I have to work a lot with XML
schemas. I will try and study the code you posted and, if it works, see
if I can incorporate into the structure I have (basically what you see
in the code I posted). Thanks and I will write later today or tomorrow
by the latest.
- Eric (WP)
>>> <xs:element name="movie" type="xs:string" foo:bar="somevalue"/>
>
> System.out.println("--- Particle annotations:");
> printAnnotations(elemParticle.getAnnotations());
>
> System.out.println("--- Element declaration annotations:");
> elemDecl = (XSElementDeclaration) elemParticle.getTerm();
> printAnnotations(elemDecl.getAnnotations());
The particle and element declaration components have the same set of
annotations because in the given case the element declaration is
local and the defining <xs:element> element represents both the
particle and the element declaration. With a top level element
declaration:
<xs:element name="movie" type="xs:string"/>
...
<xs:element ref="movie" foo:bar="somevalue"/>
...
Only the particle would get the annotation with the 'foo:bar' attribute.
--
Stanimir
I'm not quite sure I follow you now but I will study what you said later
(I'm not even supposed to work today, heh). Anyway, I turned on
generate-synthetic-annotations as you did in your code and now I get
annotations. Now I just need to figure out how to extract the
information I need from them, so I only get those that are important to
me but that shouldn't be too difficult. Just need to study the
interfaces a bit. Thanks so much, I really mean it, you have been
incredibly helpful to me and I appreciate it alot! I wish you the best!
I will play more with the code tomorrow by the latest and post back on
how things went. Thanks again!
- Eric (WP)