Thanks, I tried this, but I don't think it's quite right. I think it is
making some assumptions about the element types, so while it works for the
example, I don't think it will work generally.
For my purposes, I only needed to determine whether a local element has
element substitutions. While this means it is a global element reference,
I don't need to know that directly.
After some playing around, this is what I found seems to work:
* you need the parent SchemaType for your SchemaLocalElement
* use SchemaType#getElementProperty, with the name of your
SchemaLocalElement as the argument
* with the returned SchemaProperty, get the 'acceptedNames', and then test
which global elements have these QNames
* the matching global elements are the valid substitutions.
Cheers, Tony.
PS you can see code that implements this, albeit in Scala, in the source
code for XML Zebra (http://www.xmlzebra.com/).
On Mon, 28 Dec 2009 19:33:11 -0000, Gillen, Paul <[email protected]>
wrote:
Never occurred to me to try. I wonder what your use case is? That
having been said, this was kind of fun to dink around with. One of the
things to note is that an element can have a name the same as a global
element so simply comparing the names won't work. I think the following
(a) does what you're asking and (b) works; let me know.
My XSD (Note that "UnusedGlobal" is used both as a name for an
"ExternalType" and for a global element):
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="ATTRTEST">
<xs:complexType>
<xs:sequence>
<xs:element name="TESTELEM">
<xs:complexType>
<xs:attribute name="DEFATTR"
type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element ref="Element"/>
<xs:element name="UnusedGlobal"
type="ExternalType"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="ExternalType">
<xs:attribute name="externalTypeAttribute"
type="xs:string" use="required"/>
</xs:complexType>
<xs:element name="Element">
<xs:complexType>
<xs:attribute name="elementAttribute"
type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="UnusedGlobal">
<xs:complexType>
<xs:attribute name="elementAttribute"
type="xs:string" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
Test XML:
<?xml version="1.0" encoding="UTF-8"?>
<ATTRTEST xsi:noNamespaceSchemaLocation="../xsd/AttrTest.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<TESTELEM DEFATTR="defined attribute"/>
<Element elementAttribute="element attribute from global
element"/>
<UnusedGlobal externalTypeAttribute="attribute from complex
type"/>
</ATTRTEST>
Program (extended from earlier question; forgive extraneous bits):
package test;
import java.io.File;
import noNamespace.ATTRTESTDocument;
import org.apache.xmlbeans.QNameSet;
import org.apache.xmlbeans.SchemaGlobalElement;
import org.apache.xmlbeans.SchemaProperty;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.SchemaTypeSystem;
import org.apache.xmlbeans.XmlObject;
import org.w3c.dom.Node;
public class Atest
{
private static final QNameSet QNS =
QNameSet.forWildcardNamespaceString("##any", "*");
private ATTRTESTDocument atd;
public static void main(String[] args)
throws Exception
{
Atest mod = new Atest();
mod.go();
}
private void go()
throws Exception
{
atd = ATTRTESTDocument.Factory.parse(new
File("xml/AttrTest.xml"));
SchemaTypeSystem docSts =
atd.schemaType().getTypeSystem();
SchemaGlobalElement[] docSges = docSts.globalElements();
System.out.println("These are the global elements -
"+docSges.length);
for (SchemaGlobalElement docSge:docSges)
{
System.out.println("\t"+docSge.getName());
}
System.out.println("");
showChildAttributes(atd);
}
private void showChildAttributes(XmlObject xo)
throws Exception
{
boolean parentIsGlobal = isGlobalElement(atd, xo);
String parentName = xo.getDomNode().getLocalName();
System.out.println
(
parentName +
"(globalElement="+parentIsGlobal+"):"
);
XmlObject[] xoAttrs = xo.selectAttributes(QNS);
for (int i = 0; i < xoAttrs.length; i++)
{
Node domainNode = xoAttrs[i].getDomNode();
String childName = domainNode.getLocalName();
String childValue = domainNode.getNodeValue();
boolean isInXsd = isAttributeInSchema(xo, childName);
System.out.println
(
"\t" +
childName + "=\"" +
childValue + "\"\n\t" +
"attribute defined in XSD:" + isInXsd
);
}
XmlObject[] xoChildren = xo.selectChildren(QNS);
if (xoChildren != null)
{
for (XmlObject xoChild:xoChildren)
{
showChildAttributes(xoChild);
}
}
}
private boolean isAttributeInSchema(XmlObject xo, String name)
throws Exception
{
boolean ret = false;
SchemaType xoSt = xo.schemaType();
SchemaProperty[] xoSps = xoSt.getAttributeProperties();
for (SchemaProperty xoSp:xoSps)
{
if (xoSp.getName().toString().equals(name))
{
ret = true;
break;
}
}
return ret;
}
private boolean isGlobalElement(XmlObject doc, XmlObject xo)
{
boolean ret = false;
SchemaTypeSystem docSts =
doc.schemaType().getTypeSystem();
SchemaGlobalElement[] docSges = docSts.globalElements();
for (SchemaGlobalElement docSge:docSges)
{
ret =
docSge.getType().getComponentRef().getComponent().equals(xo.schemaType().getRef().getComponent());
if (ret)
{
break;
}
}
return ret;
}
}
Results (Note the results for "UnusedGlobal" which is a name for type
"ExternalType", not a reference to the global element of the same name):
These are the global elements - 3
UnusedGlobal
ATTRTEST
Element
null(globalElement=false):
ATTRTEST(globalElement=true):
noNamespaceSchemaLocation="../xsd/AttrTest.xsd"
attribute defined in XSD:false
TESTELEM(globalElement=false):
DEFATTR="defined attribute"
attribute defined in XSD:true
Element(globalElement=true):
elementAttribute="element attribute from global element"
attribute defined in XSD:true
UnusedGlobal(globalElement=false):
externalTypeAttribute="attribute from complex type"
attribute defined in XSD:true
Paul Gillen
-----Original Message-----
From: Anthony B. Coates (Google) [mailto:[email protected]]
Sent: Saturday, December 26, 2009 7:25 AM
To: XMLBeans Users List
Subject: How to recognise reference to global element when walking
Schema structure using Schema Object Model API?
Hi. I'm walking a Schema structure using the Schema Object Model API.
It's pretty good, I must say, but one thing I can't work out is how, when
examining the children of a complex type, you can tell which are local
elements, and which are references to global elements. Can anyone tell
me
what the trick is? Thanks very much in advance,
Cheers, Tony.
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]