如何在 Java DocumentBuilder 中解析 XSD 文件期间将元素附加到现有节点列表

Posted

技术标签:

【中文标题】如何在 Java DocumentBuilder 中解析 XSD 文件期间将元素附加到现有节点列表【英文标题】:How to append the Elements to existing Nodelist during the parse of XSD file in Java DocumentBuilder 【发布时间】:2021-06-26 06:07:48 【问题描述】:

Application Background:

基本上,我正在构建一个应用程序,在该应用程序中,我使用SAX PARSER 解析XML 文档,以获取每个传入的标签,我想知道它的datatype 和其他信息,所以我使用与关联的XSD该 XML 文件以获取 datatype 和与这些标签相关的其他信息。因此,我正在解析XSD 文件并将所有信息存储在Hashmap 中,这样每当标签出现时,我就可以将XML TAG 作为key 传递给我的Hashmap 并获得value(相关信息在 XSD 解析过程中获得的)与之关联。

Problem I am facing:

到目前为止,我可以使用DocumentBuilderFactory 解析我的XSD。但是在收集元素的过程中,我只能获取一种类型的元素并将其存储在我的NODELIST 中,例如标签名称为"xs:element" 的元素。我的 XSD 还有一些其他元素类型,例如 "xs:complexType"xs:any 等。我想读取所有这些元素并将它们存储到单个 NODELIST 中,稍后我可以循环并推送到 HASHMAP。但是,在向其添加一种类型后,我无法向 NODELIST 添加任何其他元素:

下面的代码将添加带有xs:element的标签

NodeList list = doc.getElementsByTagName("xs:element");

    如何将带有xs:complexTypexs:any 的标签添加到同一个NODELIST? 这是查找XSD 的数据类型和其他属性的好方法还是任何其他可用的更好方法。因为我可能需要为 XML 中的每个 TAG 多次点击 HASHMAP 会不会出现性能问题? DocumentBuilderFactory 是解析 XML 的好方法还是有更好的 XSD 解析库?我查看了Xerces2,但找不到任何好的例子,我很震惊并发布了问题here。

以下是我使用 DocumentBuilderFactory 解析 XSD 的代码:

公共类 DOMParser

private static Map<String, Element> xmlTags = new HashMap<String, Element>();

public static void main(String[] args) throws URISyntaxException, SAXException, IOException, ParserConfigurationException 
    String xsdPath1 = Paths.get(Xerces2Parser.class.getClassLoader().getResource("test.xsd").toURI()).toFile().getAbsolutePath();
    String filePath1 = Path.of(xsdPath1).toString();

    DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
    Document doc = docBuilder.parse(new File(filePath1));
    NodeList list = doc.getElementsByTagName("xs:element");
    System.out.println(list.getLength());
    // How to add the xs:complexType to same list as above
    // list.add(doc.getElementsByTagName("xs:complexType"));
    // list = doc.getElementsByTagName("xs:complexType");

    // Loop and add data to Map for future lookups
    for (int i = 0; i < list.getLength(); i++) 
        Element element = (Element) list.item(i);
        if (element.hasAttributes()) 
            xmlTags.put(element.getAttribute("name"), element);
        
    

【问题讨论】:

【参考方案1】:

我不知道您想要实现什么(您描述了您正在编写的代码,而不是它旨在解决的问题),但您所做的似乎被误导了。试图通过在 XML 级别解析 XSD 架构来获取有用的信息确实是一项艰巨的工作,而且从您提出的问题中可以清楚地看出您没有意识到您正在尝试的复杂性。

当我们不了解您想要实现的目标时,很难就维护哈希映射和节点列表的低级细节向您提供建议。您试图从架构中提取什么信息,为什么?

有多种方法可以从更高级别的架构中获取信息。 Xerces 有一个用于访问已编译模式的 Java API。 Saxon 有一个称为 SCM 的已编译模式的 XML 表示(与原始 XSD 的区别在于扩展 xs:include 和 xs:import、扩展属性组、模型组和替换组等的所有工作都已为您完成)。 Saxon 还有一个用于访问编译模式信息的 XPath API(一组扩展函数)。

【讨论】:

感谢您的回复。正如我在问题中提到的那样,我正在尝试从 XSD 中获取进一步处理所需的数据类型和其他属性。我需要将 XML 转换为 JSON,因此在转换过程中我想知道 XML 的每个元素的数据类型是什么,因此我使用从 XSD 创建的 HASHMAP 来获取各自的信息XML 标记。 好吧,要了解每个元素的管理类型,您需要做的远不止这些。需要区分多个同名的元素声明;您需要遵循类型派生层次结构和替换组,您需要查看元素通配符粒子,您需要了解它是如何受xsi:type 影响的。到目前为止,你只是触及了表面。 实际上,在NodeList 中,我获得了每个元素所需的所有信息。截至目前,我正在获取与 XSD 中带有标签 xs:element 的元素相关的信息。我只是想知道是否有一种方法可以以类似的方式将具有标签xs:complexType 的元素添加到相同的NODELIST。我知道我可以为 xs:complexType 创建另一个 NODELIST,但我试图跳过这一步,以便我只能拥有一个包含所有信息的 NODELIST 我不会帮你实现一个糟糕的设计,对不起。

以上是关于如何在 Java DocumentBuilder 中解析 XSD 文件期间将元素附加到现有节点列表的主要内容,如果未能解决你的问题,请参考以下文章

Java——DOM方式生成XML (转)

Java解析XML三种常用方法

DocumentBuilder.parse 是不是关闭 InputStream

DOM解析器演示使用DocumentBuilder。

当我需要 DocumentBuilder 时使用 SAX 解析器

Java自带的XML解析器接口