I am using the Apache XmlSchema Core
library to parse the XSD
file and get all the elements and its children type (datatype, maxOccurs, etc). I am following the documentation Apache XML SCHEMA CORE and trying to do. But after navigating to a certain point I am getting a bit confused. Can someone please guide me on how can I traverse through my XSD
file and get all the elements and its child elements along with the related information?
I am able to get all the XSD information in my schema
element I just want to know how can I access the child elements from my root RootFood
and get its related information. Any help would be really appreciated.
I tried to continue further and this is what I have so far:
The element RootFood
belongs to the instance of the class XmlSchemaGroupParticle
. I tried to debug the code to find the elements that are associated with my rootParticles
, it has the field called items
within which I have my food
element items->[0]->namedDelegate->qName->localPart
but when I try to add GET
method on rootParticles
to obtain the items
then there is no such method.
The XmlSchemaParticle
extends following classes: XmlSchemaAnnotated
, XmlSchemaObject
, and implements the interface XmlSchemaObjectBase
but none of them have the field called Items
.
Following is the Java code I have so far, I tried several things:
public class XMLSchemaCore {
public static void main(String[] args) throws URISyntaxException,
FileNotFoundException,
UnsupportedEncodingException {
String xsdPath = Paths.get(XMLSchemaCore.class.getClassLoader().getResource("test.xsd").toURI()).toFile().getAbsolutePath();
String filePath = Path.of(xsdPath).toString();
InputStream is = new FileInputStream(filePath);
XmlSchemaCollection schemaCol = new XmlSchemaCollection();
// Schema contain the complete XSD content which needs to be parsed
XmlSchema schema = schemaCol.read(new StreamSource(is));
// schema.write(System.out);
for (Map.Entry<QName, XmlSchemaElement> entry: schema.getElements().entrySet()) {
// Root element and its contents
QName parentElementName = entry.getKey();
XmlSchemaElement parentElementValues = entry.getValue();
// Get the elements based on the Root element
XmlSchemaElement root = schema.getElementByName(parentElementName);
// Get the type of the root element
XmlSchemaType type = root != null ? root.getSchemaType() : null;
// Check if the root element is of Complex type
if (type instanceof XmlSchemaComplexType) {
// Get the Particles associated with the element
XmlSchemaParticle rootParticles = ((XmlSchemaComplexType) type).getParticle();
// Check particle belongs to which type
if (rootParticles instanceof XmlSchemaAny) {
System.out.println("Any Schema Type");
} else if (rootParticles instanceof XmlSchemaElement) {
System.out.println("Element Schema Type");
} else if (rootParticles instanceof XmlSchemaGroupParticle) {
System.out.println("Group Schema Type");
System.out.println(rootParticles);
System.out.println(rootParticles);
} else if (rootParticles instanceof XmlSchemaGroupRef) {
System.out.println("Group Ref Schema Type");
}
}
}
}
}
Following is the XSD
file I have:
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="RootFood">
<xs:complexType>
<xs:sequence>
<xs:element name="food">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="name" />
<xs:element type="xs:string" name="price" />
<xs:element type="xs:string" name="description" />
<xs:element type="xs:short" name="calories" />
<xs:element name="ingredients">
<xs:complexType>
<xs:sequence>
<xs:element type="xs:string" name="ingredient"
maxOccurs="unbounded" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
After trying a lot of things I was able to get the code working. Posting the code here as it may help somebody who is planning to use Apache XMLSchema Core Library for XML/XSD parsing. I know how much frustrating it is as we do not have some good examples on the internet for this parsing library. Hope this helps.
Basically, this code will parse the whole XSD
file and store the elements in the HashMap
based on its parent and child element. You can obtain the Parent for any XSD element also you can get the information related to the child such as its parent etc. Check the XmlSchemaElement to get further details on the information for each child:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.xml.namespace.QName;
import javax.xml.transform.stream.StreamSource;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaAny;
import org.apache.ws.commons.schema.XmlSchemaCollection;
import org.apache.ws.commons.schema.XmlSchemaComplexType;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaGroupRef;
import org.apache.ws.commons.schema.XmlSchemaParticle;
import org.apache.ws.commons.schema.XmlSchemaSequence;
import org.apache.ws.commons.schema.XmlSchemaSequenceMember;
import org.apache.ws.commons.schema.XmlSchemaType;
public class XMLSchemaCore {
private static XmlSchemaCollection xmlSchemaCollection;
private static Map<QName, List<XmlSchemaElement>> xsdElements = new HashMap<QName, List<XmlSchemaElement>>();
private static List<XmlSchemaElement> schemaElements = new ArrayList<XmlSchemaElement>();
public static void main(String[] args) throws URISyntaxException, FileNotFoundException, UnsupportedEncodingException {
// Path for the file which is stored within the Resource folder
String xsdPath = Paths.get(XMLSchemaCore.class.getClassLoader().getResource("test.xsd").toURI()).toFile().getAbsolutePath();
String filePath = Path.of(xsdPath).toString();
InputStream is = new FileInputStream(filePath);
xmlSchemaCollection = new XmlSchemaCollection();
// Schema contain the complete XSD content which needs to be parsed
XmlSchema schema = xmlSchemaCollection.read(new StreamSource(is));
// schema.write(System.out);
// Get the root element from XSD
Map.Entry<QName, XmlSchemaElement> entry = schema.getElements().entrySet().iterator().next();
QName rootElement = entry.getKey();
// Get all the elements based on the parent element
XmlSchemaElement childElement = xmlSchemaCollection.getElementByQName(rootElement);
// Call method to get all the child elements
getChildElementNames(childElement);
String element = "" + xsdElements.entrySet().stream().map(e -> e.getKey() + " -- " + String.join(", ", e.getValue().stream().map(v -> v
.getQName().toString()).collect(Collectors.toList()))).collect(Collectors.toList());
System.out.println(element);
}
// Method to check for the child elements and return list
private static void getChildElementNames(XmlSchemaElement element) {
// Get the type of the element
XmlSchemaType elementType = element != null ? element.getSchemaType() : null;
// Confirm if the element is of Complex type
if (elementType instanceof XmlSchemaComplexType) {
// Get all particles associated with that element Type
XmlSchemaParticle allParticles = ((XmlSchemaComplexType) elementType).getParticle();
// Check particle belongs to which type
if (allParticles instanceof XmlSchemaAny) {
System.out.println("Any Schema Type");
} else if (allParticles instanceof XmlSchemaElement) {
System.out.println("Element Schema Type");
} else if (allParticles instanceof XmlSchemaSequence) {
// System.out.println("Sequence Schema Type");
final XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) allParticles;
final List<XmlSchemaSequenceMember> items = xmlSchemaSequence.getItems();
items.forEach((item) -> {
XmlSchemaElement itemElements = (XmlSchemaElement) item;
schemaElements.add(itemElements);
// System.out.println(" Parent : " + element.getQName() + " -- Child : " +
// itemElements.getQName());
//Call the method to add the current element as child
addChild(element.getQName(), itemElements);
// Call method recursively to get all subsequent element
getChildElementNames(itemElements);
schemaElements = new ArrayList<XmlSchemaElement>();
});
} else if (allParticles instanceof XmlSchemaGroupRef) {
}
}
}
// Add child elements based on its parent
public static void addChild(QName qName, XmlSchemaElement child) {
List<XmlSchemaElement> values = xsdElements.get(qName);
if (values == null) {
values = new ArrayList<XmlSchemaElement>();
}
values.add(child);
xsdElements.put(qName, values);
}
}