Ваш возможный подход (преобразование двух 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