0

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

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

例如:在 myXSD中,RestaurantMenuRoot元素,它的直接子元素是Food。此外,Food还有 childrens namepricecalories。当我看到 parent 元素时,name我希望它是Food直接的 Parent 但在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));

上面的代码将返回Children食物的所有元素:name, price, calories, description, ingredients。然后我试图查看其中一个元素的父级,即name. 以下是我正在采用的调试路径:

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

在这qName我期待那food是我的直接父母,但我得到了RestaurantMenu这是我的Rootxsd 元素。

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

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

2 回答 2

0

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

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

于 2021-04-09T09:28:42.833 回答
0

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

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

您能否帮助我在 Apache XMLSchema 核心库中找到子元素的直接父级。

当您谈论“子元素”时,我认为您的意思是 alocal element declaration或 an element reference。通常,它们都可以有多个父元素声明,因为它们可以在全局复杂类型中声明。如果该全局复杂类型定义被多个元素声明使用,那么您的“子元素”将具有多个可能的父元素。

于 2021-04-01T18:40:02.177 回答