0

我正在编写一些应该比较两个 XML 文档的 XML结构的功能测试。这意味着标签顺序和命名很重要,而标签内容无关紧要。

例如,以下调用:

呼叫 1:

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book category="COOKING">
    <title lang="en">Everyday Italian</title>
    <author>Giada De Laurentiis</author>
  </book>
</bookstore>

呼叫 2:

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book category="CHILDREN">
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
  </book>
</bookstore>

具有相同的标签结构,但是:

呼叫 3:

<?xml version="1.0" encoding="UTF-8"?>
<bookstore>
  <book category="WEB">
    <title lang="en">Learning XML</title>
    <author>Erik T. Ray</author>
    <year>2003</year>
  </book>
</bookstore>

不同,因为它在<year>之后有一个标签<author>,并且调用 1 和 2 缺少该标签。

比较 XML 结构的 Java 方法是什么?

4

2 回答 2

1

您可以对两个文档调用一个简单的 XSLT 转换,去除所有文本节点和属性内容,然后对两个结果调用 XPath deep-equal()。

于 2013-05-23T13:53:32.730 回答
0

我编写了一个扁平化 XML 并提供人类可读的字符串进行比较的类。

出于比较的目的,我创建了两个XPathFlattener对象,并比较它们的toString()表示。

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.w3c.dom.Node;

public class XPathFlattener {

    private Node root;

    public XPathFlattener(Node root) {
        this.root = root;
    }

    /**
     * Flattens a XPath tree to a list of nodes, in pre-order traversal.
     */
    public List<Node> flatten() {
        List<Node> nodes = flattenTreeToList(this.root, new ArrayList<Node>());
        return nodes; 
    }

    /**
     * Flattens a XPath tree to a list of Strings, each representing the name
     * of the node, but not its contents. 
     * The list is created using pre-order traversal.
     */
    @Override
    public String toString() {
        List<String> nodesStrings = new ArrayList<>();
        for (Node n:this.flatten()) {
            nodesStrings.add(stringRepresentation(n));
        }
        return StringUtils.join(nodesStrings, ", ");
    }

    /**
     * Recursively flattens a Node tree to a list, in pre-order traversal.
     * @param node
     * @param nodes
     * @return
     */
    private static List<Node> flattenTreeToList(Node node, List<Node> nodes) {
        nodes.add(node);
        for (int i=0; i< node.getChildNodes().getLength(); i++) {
            Node childNode = node.getChildNodes().item(i);
            flattenTreeToList(childNode, nodes);
        }
        return nodes;
    }

    /**
     * A String representation of the node structure, without its contents.
     * @param node
     * @return
     */
    private static String stringRepresentation(Node node) {
        return String.format("[%s, (type %d)]", node.getNodeName(), node.getNodeType());
    }

}
于 2013-05-23T14:08:13.397 回答