简体   繁体   English

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

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

I am trying to parse the XSD using Apache XMLSchema Core .我正在尝试使用Apache XMLSchema Core解析XSD I am able to parse the file and store the Parent and its Child Element information within the HashMap .我能够解析文件并将Parent元素及其Child Element信息存储在HashMap中。

Each Child element is stored in the type XmlSchemaElement which also consists of the Parent information of that child element.每个Child元素都存储在XmlSchemaElement类型中,该类型还包含该子元素的Parent信息。 When I try to see the information related to a child element it shows the Root element for all instead of its immediate parent.当我尝试查看与子元素相关的信息时,它会显示所有的Root元素而不是其直接父元素。

For example: In my XSD , RestaurantMenu is the Root element and its immediate children are Food .例如:在我的XSD中, RestaurantMenuRoot元素,其直接子元素是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.此外, Food有子namepricecalories等。当我看到name的父元素时,我希望它是Food ,因为那是直接父元素,但在Debug期间将RestaurantMenu显示为其父元素,这有点令人困惑。

I wanted to know how can I get the information related to the immediate parent for each element.我想知道如何获取与每个元素的直接父级相关的信息。

Following is my XSD file:以下是我的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>

Following is the code I have which is written using the Apache XmlSchema Core XML Parser : I am trying to Debug at the point:以下是我使用Apache XmlSchema Core XML Parser编写的代码:我正在尝试Debug

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 .上面的代码将返回食物的所有Children元素: namepricecaloriesdescriptioningredients Then I am trying to see the parent for one of the element ie name .然后我试图查看其中一个元素的父级,即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.在这个qName中,我期待food是我的直系父母,但我得到了RestaurantMenu ,它是我的Root xsd 元素。

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

Disclaimer: I am not an expert in XSModel, but I did use it once, a long time ago.免责声明:我不是 XSModel 方面的专家,但我确实使用过一次,很久以前。

The XSModel is a full and complete record of almost everything in the XSDs. XSModel 是 XSD 中几乎所有内容的完整记录。 Therefore it does contain the information that you are seeking.因此,它确实包含您正在寻找的信息。 It may help to realise that XSModel was created for the purpose of validating XML documents - it was never intended to be a general-purpose in-memory representation of an XSD model.可能有助于意识到 XSModel 是为了验证 XML 文档而创建的 - 它从未打算成为 XSD model 的通用内存表示。 If that's what you need then you will probably get on better with the Eclipse XSD model .如果这就是您所需要的,那么您可能会更好地使用Eclipse XSD model Either way, loading and manipulating XSD models is a minority sport and you should not expect the APIs to be perfectly documented.无论哪种方式,加载和操作 XSD 模型都是一项少数运动,您不应期望 API 会被完美记录。

Can you please assist me in how to find an immediate parent for a child element within the Apache XMLSchema core library.您能否帮助我在 Apache XMLSchema 核心库中找到子元素的直接父级。

When you talk about a 'child element' I think you mean either a local element declaration or an element reference .当您谈论“子元素”时,我认为您的意思是local element declarationelement reference In general, both of those can have multiple parent element declarations because they can be declared within a global complex type.通常,它们都可以有多个父元素声明,因为它们可以在全局复杂类型中声明。 If that global complex type definition is used by more than one element declaration then your 'child element' will have more than one possible parent element.如果该全局复杂类型定义被多个元素声明使用,那么您的“子元素”将具有多个可能的父元素。

After working for some time on the Apache XMLSchema Core library in Java following is my observation.在 Java 中的Apache XMLSchema Core库上工作了一段时间后,以下是我的观察。

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.无法使用库直接获取直接父级,您可以从 XmlSchemaElement 获取与当前元素及其子级相关的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM