I am trying to parse the XSD
using Apache XMLSchema Core
. I am able to parse the file and store the Parent
and its Child Element
information within the HashMap
.
Each Child
element is stored in the type XmlSchemaElement
which also consists of the Parent
information of that child element. When I try to see the information related to a child element it shows the Root
element for all instead of its immediate parent.
For example: In my XSD
, RestaurantMenu
is the Root
element and its immediate children are Food
. Also, Food
has childrens name
, price
, calories
etc. When I see the parent element for name
I would expect it to be Food
as that's the immediate Parent but during Debug
shows the RestaurantMenu
as its parent which is a bit confusing.
I wanted to know how can I get the information related to the immediate parent for each element.
Following is my XSD
file:
<xs:schema attributeFormDefault="unqualified"
elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="RestaurantMenu">
<xs:complexType>
<xs:sequence>
<xs:element name="food" maxOccurs="5" minOccurs="0">
<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:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Following is the code I have which is written using the Apache XmlSchema Core XML Parser
:
I am trying to Debug
at the point :
List<XmlSchemaElement> childElements = getElementType(new QName("food"));
System.out.println(childElements.get(0));
Above code will return all the Children
element of food: name
, price
, calories
, description
, ingredients
. Then I am trying to see the parent for one of the element i.e name
. Following is the debug path I am taking:
childElements -> [0] -> namedDelegate -> parentSchema -> items -> [0] -> namedDelegate -> qName.
In this qName
I was expecting the food
as thats my immediate parent but I get the RestaurantMenu
which is my Root
xsd element.
Please find the complete code below:
public class TestParser {
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(TestParser.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();
// Get all the elements based on the parent element
XmlSchemaElement childElement = xmlSchemaCollection.getElementByQName(entry.getKey());
// Call method to get all the child elements
getChildElementNames(childElement);
// Get the elements type based on choice
List<XmlSchemaElement> childElements = xsdElements.get(new QName("food"));
System.out.println(childElements.get(0));
}
// 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 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);
addChild(element.getQName(), itemElements);
// Call method recursively to get all subsequent element
getChildElementNames(itemElements);
schemaElements = new ArrayList<XmlSchemaElement>();
});
}
}
}
// Add child elements based on its parent
private 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);
}
}
After working for some time on the Apache XMLSchema Core
library in Java following is my observation.
There is no way to get the immediate parent directly using the library you can get the information related to the current element and its children from the XmlSchemaElement.