有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

xml-Java:比较XPath结构

我正在编写一些功能测试,比较两个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>

是不同的,因为它在<author>之后有一个<year>标记,而调用1和2缺少该标记

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


共 (2) 个答案

  1. # 1 楼答案

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

  2. # 2 楼答案

    我编写了一个类,该类将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());
        }
    
    }