您可能的方法(转换两个 XML 并比较节点)很好,但您不比较路径,而是在导航节点时并行比较节点。
正如您所说,这假定名称是唯一的。
例如像这样,使用递归方法:
public static void checkXml(String templateXml, String dataXml) throws Exception {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder domBuilder = domFactory.newDocumentBuilder();
Element templateRoot = domBuilder.parse(new InputSource(new StringReader(templateXml))).getDocumentElement();
Element dataRoot = domBuilder.parse(new InputSource(new StringReader(dataXml))).getDocumentElement();
if (! templateRoot.getNodeName().equals(dataRoot.getNodeName()))
throw new IllegalArgumentException("Different root elements: " + dataRoot.getNodeName() +
" != " + templateRoot.getNodeName());
checkChildren(templateRoot, dataRoot, dataRoot.getNodeName());
}
private static void checkChildren(Node templateParent, Node dataParent, String parentPath) {
for (Node templateChild = templateParent.getFirstChild(); templateChild != null; templateChild = templateChild.getNextSibling()) {
if (templateChild.getNodeType() == Node.ELEMENT_NODE) {
String childPath = parentPath + "/" + templateChild.getNodeName();
Node dataChild = getChild(dataParent, templateChild.getNodeName());
if (dataChild == null)
throw new IllegalArgumentException("Missing child: " + childPath);
checkChildren(templateChild, dataChild, childPath);
}
}
}
private static Node getChild(Node parent, String name) {
for (Node child = parent.getFirstChild(); child != null; child = child.getNextSibling())
if (child.getNodeType() == Node.ELEMENT_NODE && child.getNodeName().equals(name))
return child;
return null;
}
测试
public static void main(String[] args) throws Exception {
String template = "<A><B/><C><E></E></C></A>";
String xml1 = "<A><B/><C><D></D><E/></C><F/></A>"; //Compliant to Template: the structure is kept
String xml2 = "<A><B><E/></B><C/></A>"; //Not compliant to Template: E is child of B here, while E is child of C in Template
String xml3 = "<A><C><E/><D/></C><F></F><B/></A>"; //Compliant to Template: the order of children doesn't matter
test(template, xml1);
test(template, xml2);
test(template, xml3);
}
private static void test(String templateXml, String dataXml) throws Exception {
try {
checkXml(templateXml, dataXml);
System.out.println("Ok");
} catch (IllegalArgumentException e) {
System.out.println(e.getMessage());
} catch (Exception e) {
System.out.println(e);
}
}
输出
Ok
Missing child: A/C/E
Ok