我正在编写一些功能测试,它们应该比较两个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方法是什么?
答案 0 :(得分:1)
您可以在两个文档上调用简单的XSLT转换,删除所有文本节点和属性内容,然后在两个结果上调用XPath deep-equal()。
答案 1 :(得分:0)
我编写了一个扁平化XML的类,并提供了一个人类可读的String来进行比较。
为了进行比较,我创建了两个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());
}
}