Apache XMLSchema 核心 XSD/XML 解析器将根元素显示为所有子元素的父元素,而不是其直接父元素

Apache XMLSchema core XSD/XML parser shows the root element as parent for all children instead of its immediate parent

我正在尝试使用 Apache XMLSchema Core 解析 XSD。我能够解析文件并将 Parent 及其 Child Element 信息存储在 HashMap.

每个 Child 元素都存储在类型 XmlSchemaElement 中,该类型还包含该子元素的 Parent 信息。当我尝试查看与子元素相关的信息时,它显示所有元素的 Root 元素而不是其直接父元素。

例如:在我的 XSD 中,RestaurantMenuRoot 元素,它的直接子元素是 Food。此外,Food 有子元素 namepricecalories 等。当我看到 name 的父元素时,我希望它是 Food 因为那是直接父级,但在 Debug 期间显示 RestaurantMenu 作为其父级,这有点令人困惑。

我想知道如何获取与每个元素的直接父元素相关的信息。

以下是我的 XSD 文件:

<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>

以下是我使用 Apache XmlSchema Core XML Parser 编写的代码: 我正在尝试 Debug 点 :

List<XmlSchemaElement> childElements = getElementType(new QName("food"));
System.out.println(childElements.get(0));

以上代码将 return 食物的所有 Children 元素:namepricecaloriesdescriptioningredients。然后我试图查看其中一个元素的父元素,即 name。以下是我正在使用的调试路径:

childElements -> [0] -> namedDelegate -> parentSchema -> items -> [0] -> namedDelegate -> qName.

在这个 qName 中,我期待 food 是我的直接父元素,但我得到 RestaurantMenu 这是我的 Root xsd 元素。

请在下面找到完整的代码:

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);
    }
}

免责声明:我不是 XSModel 方面的专家,但很久以前我确实用过一次。

XSModel 是 XSD 中几乎所有内容的完整完整记录。因此它确实包含您正在寻找的信息。意识到 XSModel 是为了验证 XML 文档而创建的可能会有所帮助 - 它从未打算成为 XSD 模型的通用内存表示。如果那是您所需要的,那么您可能会更好地使用 Eclipse XSD model。无论哪种方式,加载和操作 XSD 模型都是少数人的运动,您不应该期望 API 得到完美的记录。

Can you please assist me in how to find an immediate parent for a child element within the Apache XMLSchema core library.

当您谈论 'child element' 时,我认为您指的是 local element declarationelement reference。通常,它们都可以有 多个 父元素声明,因为它们可以在全局复杂类型中声明。如果该全局复杂类型定义被多个元素声明使用,那么您的 'child element' 将有多个可能的父元素。

在 Java 的 Apache XMLSchema Core 库上工作了一段时间后,以下是我的观察。

无法直接使用库获取直接父元素,您可以从 XmlSchemaElement 中获取与当前元素及其子元素相关的信息。