是否可以在没有嵌套循环的情况下读取整个 XML 文件

Posted

技术标签:

【中文标题】是否可以在没有嵌套循环的情况下读取整个 XML 文件【英文标题】:Is it possible to read whole XML file without nested loops 【发布时间】:2021-09-17 00:55:28 【问题描述】:

我是 XML 新手,我想获得有关任务的帮助。我需要为 XML 文件编写一个解析器(见下文)。解析器应返回HashTable<String, List<String>>,其中键是操作名称,列表包含参数名称,其顺序与这些名称在 XML 文件中出现的顺序相同。这里最重要的是参数名称的顺序。 XML:

....
<actions>
    <action>
            <name>ActionName1</name>
            <arguments>
                <argument>
                    <name>name1</name>
                    <type>type1</type>
                    <comment>comment</comment>
                </argument>
                 <argument>
                      <name>name2</name>
                      <type>type2</type>
                      <comment>comment</comment>
                 </argument>
                   <argument>
                       <name>name3</name>
                       <type>type3</type>
                       <comment>comment</comment>
                   </argument>
            </arguments>
        </action>
        <action>
            <name>ActionName2</name>
            <arguments>
                  ...
            </arguments>
        </action>   
 </actions>

代码:

 ...   
    String expression = "//actions/action";
    XPathExpression compiled = xPath.compile(expression);
    nodeList = (NodeList) compiled.evaluate(document, XPathConstants.NODESET);
 
    for (int i = 0; i < nodeList.getLength(); i++) 
                 
         Node node = nodeList.item(i);
         NodeList children = node.getChildNodes();
                 
         for (int j = 0; j < children.getLength(); j++) 
              Node child = children.item(j);
              
              if (child.getNodeName().equals("name")) 
                //add new entry to map, meanwhile just print it
                 System.out.println(child.getTextContent());
                 continue;
              
              
              if (child.getNodeName().equals("arguments")) 
                Element element = (Element) child;
                NodeList names = element.getElementsByTagName("name");
                for (int k = 0; k < names.getLength() ; k++) 
                     Node nameNode = names.item(k);
                     //add element to list, meanwhile print it
                     System.out.println("\t" + nameNode.getTextContent());
                
                     
    

代码可以运行,但它非常庞大并且有 2 个嵌套循环。 有没有更有效和简单的方法来实现所需的功能? 提前致谢。

【问题讨论】:

【参考方案1】:

您可以考虑使用 Saxon 10 HE(或 Saxon 9.8 或 9.9 HE)迁移到 XPath 3.1,然后您的 XPath 将变得简单

map:merge(//action!map  name : arguments/argument/name/string() )

map:merge(//action!map  name : array  arguments/argument/name/string() )

然后使用 s9api 它应该能够从 XPath 3.1 XDM 映射到您的 Java HashTable 或简单地使用 XDM 映射:

    Processor processor = new Processor(true);

    DocumentBuilder docBuilder = processor.newDocumentBuilder();

    XdmNode input = docBuilder.build(new File("sample-actions1.xml"));

    XPathCompiler xpathCompiler = processor.newXPathCompiler();

    xpathCompiler.declareNamespace("map", "http://www.w3.org/2005/xpath-functions/map");

    XdmMap result = (XdmMap)xpathCompiler.evaluateSingle("map:merge(//action!map  string(name) : arguments/argument/name/string() )", input);

    System.out.println(result);

【讨论】:

以上是关于是否可以在没有嵌套循环的情况下读取整个 XML 文件的主要内容,如果未能解决你的问题,请参考以下文章

嵌套 foreach 循环读取 .xml 并将对象写入列表

在相应目录下新建或读取xml文件

在 PHP 中不使用太多内存的情况下读取/写入大型 XML

有没有办法在没有嵌套循环的情况下遍历数字列表的所有组合?

是否有 ruby​​ oneliner 可以在没有临时副本的情况下连接嵌套数组?

在“try”运算符中嵌套“for”循环