Java:比较XPath结构
我正在编写一些功能测试,比较两个XML文档的XML结构。这意味着标记顺序和命名是重要的,而标记内容是无关的 例如,以下调用: 电话1:Java:比较XPath结构,java,xml,xpath,functional-testing,Java,Xml,Xpath,Functional Testing,我正在编写一些功能测试,比较两个XML文档的XML结构。这意味着标记顺序和命名是重要的,而标记内容是无关的 例如,以下调用: 电话1: <?xml version="1.0" encoding="UTF-8"?> <bookstore> <book category="COOKING"> <title lang="en">Everyday Italian</title> <author>Giada De
<?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>
是不同的,因为它后面有一个标记,而调用1和2缺少该标记
比较XML结构的Java方法是什么?您可以对这两个文档调用一个简单的XSLT转换,去掉所有文本节点和属性内容,然后对这两个结果调用XPath deep equal。我编写了一个类,它将XML展平,并提供一个人类可读的字符串进行比较 为了进行比较,我创建了两个XPathFlatter对象,并比较它们的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());
}
}
你所说的比较是什么意思?打印差异?打印差异会有好处,但即使打印第一个不同的节点也可以。我以前用Java做过XML比较过程,抱歉,无法共享代码。这不是小事。对于您所展示的结构,每个元素都可以使用一个相对简单的循环。我遇到的问题主要是性能,以及如何显示差异。如果你想要更一般的比较,那么你应该看看LCS算法:谢谢@rolfl,这是一条有用的信息。我不在乎性能,我也不需要一个别致的diff-like查看器。如果我找不到现成的解决方案,我可能只写一个并发布在Github上。你有针对这些XML的方案吗?可以帮助你很多。你能提供一个链接吗?一个Java代码示例将非常有用。我目前正在探索Apache Xalan,我不确定这是一条路。对不起,我在这里回答问题,要么是因为它们很有趣,要么是因为它们可以在几秒钟内得到回答,而这一个不属于这两个类别。我建议使用deep equal需要XSLT 2.0,Xalan不支持这一点;你想用撒克逊来做这个。