从xml文件读取数据并存储为键值对

时间:2019-12-12 05:48:26

标签: java xml xml-parsing

我在存储一些测试数据的XML文件中有以下数据。

<root>
    <event>
        <auth>
            <admin>
                <username>testust@mail.com</username>
                <password>pass^&*%s</password>
                <name>temp</name>
            </admin>

            <normal-user>
                <username>test_usera1@mail.com</username>
                <password>test45#</password>
            </normal-user>

        </auth>
    </event>
</root>

我正在尝试从键值对中的xml读取数据。 例如event.auth.admin.username = testust@mail.com。如果我将所有其他数据节点置于admin下,但如果我使用另一个节点<normal-user>,则它将此节点名称附加到较旧的节点中,这样可以正常工作。

实际:event.auth.admin.normal-user.username = test_usera1@mail.com

预期:event.auth.normal-user.username = testust@mail.com

我正在使用以下代码:

private StringBuilder keyName = new StringBuilder();
Logger printLog = Logger.getLogger("API Testing Logger");

public void loadXml() {
    File folder = new File("resources");
    File[] listOfFiles = folder.listFiles();

    for (File file : listOfFiles) {
        if (file.isFile() && file.getName().endsWith(".xml")) {

            printLog.log(Level.INFO, "xml file loaded : " + file.getName());

            try {
                File inputFile = new File(folder.getAbsolutePath() + "/" + file.getName());
                DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
                DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
                Document doc = dBuilder.parse(inputFile);
                doc.getDocumentElement().normalize();
                new XmlLoader().fillDataInProperty(doc.getDocumentElement());

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

public void fillDataInProperty(Node node) {

    if (!node.getNodeName().equals("root")) {

        if (node.getChildNodes().getLength() == 1) {
            keyName.append(node.getNodeName());
            int i = keyName.indexOf(node.getNodeName());
            if (i != -1) {
                keyName.delete(i, i + keyName.length());
            }

        } else {
            keyName.append( node.getNodeName().concat("."));

        }
    }

    NodeList nodeList = node.getChildNodes();
    for (int i = 0; i < nodeList.getLength(); i++) {

        Node currentNode = nodeList.item(i);
        if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
            fillDataInProperty(currentNode);
        }
    }
}

2 个答案:

答案 0 :(得分:1)

问题是当您有多个子节点时,这是一种递归解决方案,试图解决该问题:

public void loadXml() {
  // ..
  new XmlLoader().fillDataInProperty(doc.getDocumentElement(), "");
}
public void fillDataInProperty(Node node, String parent) {
    if (parent.isEmpty()) {
        parent = node.getNodeName();
    } else {
        parent = parent + "." + node.getNodeName();
    }

    NodeList childNodes = node.getChildNodes();
    for (int i=0; i< node.getChildNodes().getLength(); i++) {
        Node currentNode = childNodes.item(i);
        if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
            fillDataInProperty(currentNode, parent);
        } else if (currentNode.getNodeType() == Node.TEXT_NODE && childNodes.getLength() == 1) {
            keyName.append(parent + " = " + currentNode.getTextContent().trim(); + "\n");
        }
    }
}

System.out.println(p.keyName.toString());现在将打印:

root.event.auth.admin.username = testust@mail.com
root.event.auth.admin.password = passs
root.event.auth.admin.name = temp
root.event.auth.normal-user.username = test_usera1@mail.com
root.event.auth.normal-user.password = test45#

答案 1 :(得分:1)

我发现将算法分解为以下步骤更容易:

  1. 收集所有叶子元素,即没有任何子元素的元素
  2. 对于每个叶子元素,通过沿父链向上移动来构造键名称,并通过获取叶子文本数据来构造键值:

这是一个完整的例子:

static String XML =
        "<root>\n" +
        "    <event>\n" +
        "        <auth>\n" +
        "            <admin>\n" +
        "                <username>testust@mail.com</username>\n" +
        "                <password>pass</password>\n" +
        "                <name>temp</name>\n" +
        "            </admin>\n" +
        "\n" +
        "            <normal-user>\n" +
        "                <username>test_usera1@mail.com</username>\n" +
        "                <password>test45#</password>\n" +
        "            </normal-user>\n" +
        "\n" +
        "        </auth>\n" +
        "    </event>\n" +
        "</root>";

public static void main(String[] args) throws Exception {
    Document doc = DocumentBuilderFactory
            .newInstance()
            .newDocumentBuilder()
            .parse(new ByteArrayInputStream(XML.getBytes()));
    Element root = doc.getDocumentElement();

    List<Element> leafs = new ArrayList<>();
    gatherLeafElements(root, leafs);
    for(Element e: leafs) {
        System.out.println(createProperty(root, e));
    }
}

static String createProperty(Element root, Element leaf) {
    List<String> stack = new ArrayList<>();
    Element tmp = leaf;
    while(tmp != root) {
        stack.add(0, tmp.getNodeName());
        tmp = (Element) tmp.getParentNode();
    }
    String property = stack
        .stream()
        .collect(Collectors.joining("."));
    return property + "=" + leaf.getTextContent().trim();
}

static void gatherLeafElements(Element e, List<Element> leafs) {
    if (isLeafElement(e)) {
        leafs.add(e);
        return;
    }
    Node child = e.getFirstChild();
    while(child != null) {
        if (child.getNodeType() == Node.ELEMENT_NODE) {
            gatherLeafElements((Element) child, leafs);
        }
        child = child.getNextSibling();
    }
}

static boolean isLeafElement(Element e) {
    Node child = e.getFirstChild();
    while(child != null) {
        if (child.getNodeType() == Node.ELEMENT_NODE) {
            return false;
        }
        child = child.getNextSibling();
    }
    return true;
}