XMLParsing,动态结构,内容

时间:2018-05-02 10:47:20

标签: java xml domparser

想要实现:

获取未知XML文件的元素(元素名称,xml文件中有多少元素)。

然后获取所有属性及其名称和值以便稍后使用(例如,与其他xml文件比较)

element_vs_attribute

研究之: 1. 2. 3. 4. 5. 还有更多

有人对此有任何想法吗?

我不想在前面的代码片段中预先定义超过500个表,不知怎的,我应该能够动态地获取元素的数量和元素名称。

EDIT!

Example1
<Root Attri1="" Attri2="">
    <element1 EAttri1="" EAttri2=""/>
    <Element2 EAttri1="" EAttri2="">
        <nestedelement3 NEAttri1="" NEAttri2=""/>
    </Element2> 
</Root>

Example2
<Root Attri1="" Attri2="" Attr="" At="">
    <element1 EAttri1="" EAttri2="">
        <nestedElement2 EAttri1="" EAttri2="">
            <nestedelement3 NEAttri1="" NEAttri2=""/>
        </nestedElement2>
    </element1> 
</Root>

程序Snipet:

String Example1[] = {"element1","Element2","nestedelement3"};
String Example2[] = {"element1","nestedElement2","nestedelement3"};


for(int i=0;i<Example1.length;++){
    NodeList Elements = oldDOC.getElementsByTagName(Example1[i]);
    for(int j=0;j<Elements.getLength();j++) {
        Node nodeinfo=Elements.item(j);
        for(int l=0;l<nodeinfo.getAttributes().getLength();l++) {
        .....
    }
}

输出: 预期的结果是从XML文件中获取所有Element和所有属性,而无需预先定义任何内容。

例如:

Elements: element1 Element2 nestedelement3

Attributes:  Attri1 Attri2 EAttri1 EAttri2 EAttri1 EAttri2 NEAttri1 NEAttri2

1 个答案:

答案 0 :(得分:1)

这项工作的正确工具是xpath 它允许您根据各种标准收集所有或部分元素和属性。这是你最接近&#34;通用&#34; xml解析器。

这是我提出的解决方案。解决方案首先在给定的xml doc中查找所有元素名称,然后对于每个元素,它计算元素的出现次数,然后将其全部收集到地图中。属性相同。
我添加了内联注释和方法/变量名称应该是自我解释的。

import java.io.*;
import java.nio.file.*;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

import org.w3c.dom.*;

import javax.xml.parsers.*;
import javax.xml.xpath.*;

public class TestXpath
{

    public static void main(String[] args) {

        XPath xPath = XPathFactory.newInstance().newXPath();

        try (InputStream is = Files.newInputStream(Paths.get("C://temp/test.xml"))) {
            // parse file into xml doc
            DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
            Document xmlDocument = builder.parse(is);

            // find all element names in xml doc
            Set<String> allElementNames = findNames(xmlDocument, xPath.compile("//*[name()]"));
            // for each name, count occurrences, and collect to map
            Map<String, Integer> elementsAndOccurrences = allElementNames.stream()
                .collect(Collectors.toMap(Function.identity(), name -> countElementOccurrences(xmlDocument, name)));
            System.out.println(elementsAndOccurrences);

            // find all attribute names in xml doc
            Set<String> allAttributeNames = findNames(xmlDocument, xPath.compile("//@*"));
            // for each name, count occurrences, and collect to map
            Map<String, Integer> attributesAndOccurrences = allAttributeNames.stream()
                .collect(Collectors.toMap(Function.identity(), name -> countAttributeOccurrences(xmlDocument, name)));
            System.out.println(attributesAndOccurrences);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static Set<String> findNames(Document xmlDoc, XPathExpression xpathExpr) {
        try {
            NodeList nodeList = (NodeList)xpathExpr.evaluate(xmlDoc, XPathConstants.NODESET);
            // convert nodeList to set of node names
            return IntStream.range(0, nodeList.getLength())
                .mapToObj(i -> nodeList.item(i).getNodeName())
                .collect(Collectors.toSet());
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return new HashSet<>();
    }

    public static int countElementOccurrences(Document xmlDoc, String elementName) {
        return countOccurrences(xmlDoc, elementName, "count(//*[name()='" + elementName + "'])");
    }

    public static int countAttributeOccurrences(Document xmlDoc, String attributeName) {
        return countOccurrences(xmlDoc, attributeName, "count(//@*[name()='" + attributeName + "'])");
    }

    public static int countOccurrences(Document xmlDoc, String name, String xpathExpr) {
        XPath xPath = XPathFactory.newInstance().newXPath();
        try {
            Number count = (Number)xPath.compile(xpathExpr).evaluate(xmlDoc, XPathConstants.NUMBER);
            return count.intValue();
        } catch (XPathExpressionException e) {
            e.printStackTrace();
        }
        return 0;
    }
}