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

Posted

技术标签:

【中文标题】Apache XMLSchema 核心 XSD/XML 解析器将根元素显示为所有子元素的父元素,而不是其直接父元素【英文标题】:Apache XMLSchema core XSD/XML parser shows the root element as parent for all children instead of its immediate parent 【发布时间】:2021-06-28 06:01:39 【问题描述】:

我正在尝试使用 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));

上面的代码将返回食物的所有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);
    

【问题讨论】:

请您简化您的问题。那里的信息太多了。如有必要,减少您的 XSD 和代码,直到它们仅显示您所询问的问题。 @kimbert 感谢您的回复。为了更好地阅读,我减少了我的XSD 内容和代码。希望这可以帮助。请看一下,让我知道您是否可以针对此问题提出建议,因为我仍在寻找答案。 为什么你希望 parentSchema -> items -> [0] 包含特定元素的父元素?当然,parentSchema 代表整个模式模型,而 parentSchema->items 可能代表***声明(或其他东西)。建议您检查您的假设。 @kimbert 感谢您分析并提供您的解决方案。是的,后来我意识到了。我正在查看parentSchema,它可能不包含该元素的直接父级。如果不包含,那么如何获取child 的父元素?有没有其他方法可以为孩子获取immediate parentElement 【参考方案1】:

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

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

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

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

【讨论】:

感谢您的回复和信息。我仍在寻找如何找到我的子元素的直接父级。您能否帮助我在Apache XMLSchema core 库中找到子元素的直接父级。我知道它包含我所需的信息,但我不确定如何以及在哪里找到它。因此,我在这里请求希望得到一些回应。 答案已更新。您已经针对 XSModel 提出了三个不同的问题,但我仍然不清楚您要完成什么。如果您需要进一步的帮助,请确保您的下一个问题解释了您的程序的用途 - 如果我们了解您的技术目标,我们可能会提供更有用的答案。【参考方案2】:

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

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

【讨论】:

以上是关于Apache XMLSchema 核心 XSD/XML 解析器将根元素显示为所有子元素的父元素,而不是其直接父元素的主要内容,如果未能解决你的问题,请参考以下文章

Axis2错误 - java.lang.NoClassDefFoundError:org / apache / ws / commons / schema / XmlSchema

pom.xml

Maven详解

如何使用 Java 和 XmlSchema Core 解析 XSD 并读取所有复杂元素及其子元素

apache ftp server 设置

Mybaitis-generator生成数据对象和时间的优化