XML Subsets
Most applications today use XML for some form of data
saving. In testing we also need to validate XML files, find entries in the XML
via XPath and search for differences in the XML.
This lib knows how to compare XML files, and other actions
like:
·
The differences between two
pieces of XML
·
The outcome of transforming
a piece of XML using XSLT
·
The evaluation of an XPath
expression on a piece of XML
·
The validity of a piece of
XML
·
Individual nodes in a piece
of XML that are exposed by DOM Traversal
One feature that I needed that it did not support is to
detect if one XML is a subset of another. For example
I would like to check the following XML is a subset of the
next one.
<a>
<b>
test b
</b>
</a>
<a>
<b>
test a
</b>
<b>
test b
</b>
</a>
As you can guess a simple compare will fail since it will
compare the first node of b in both XML’s and since the elements are not same
it fails. What we need to do is to recursively search all nodes that have the
same name and check if they are the same and not to stop on the first. This
problem of course is not just on nodes but on attributes as well. If you need
this functionally then you can grab the code below:
public class XmlSubsetHelper {
static private boolean
equalNotNullPointers(Object a, Object b) {
if ((a == null && b != null) || (a != null && b == null)) {
return false;
}
return true;
}
static public boolean
isSubset(NamedNodeMap namedNodeMapA,
NamedNodeMap
namedNodeMapB) {
if (!equalNotNullPointers(namedNodeMapA,
namedNodeMapB)) {
return false;
}
if ((namedNodeMapA == null &&
namedNodeMapB == null)) {
return true;
}
for (int i = 0; i <
namedNodeMapA.getLength(); i++) {
Node
itemA = namedNodeMapA.item(i);
Node
itemB = namedNodeMapB.getNamedItem(itemA.getNodeName());
if (itemB == null) {
return false;
}
if
(!itemA.getNodeValue().equals(itemB.getNodeValue())) {
return false;
}
}
return true;
}
static public boolean isSubset(NodeList
childNodesA, NodeList childNodesB) {
if (!equalNotNullPointers(childNodesA,
childNodesB)) {
return false;
}
if ((childNodesA == null &&
childNodesB == null)) {
return true;
}
for (int a = 0; a <
childNodesA.getLength(); a++) {
boolean foundMatch = false;
Node
itemA = childNodesA.item(a);
for (int b = 0; b <
childNodesB.getLength(); b++) {
Node
itemB = childNodesB.item(b);
if (isSubset(itemA,
itemB)) {
foundMatch
= true;
break;
}
}
if (!foundMatch) {
return false;
}
}
return true;
}
static public boolean isSubset(Node nodeA,
Node nodeB) {
if (!equalNotNullPointers(nodeA,
nodeB)) {
return false;
}
if ((nodeA == null && nodeB == null)) {
return true;
}
if
(!nodeA.getNodeName().equals(nodeB.getNodeName())) {
return false;
}
if (!isSubset(nodeA.getChildNodes(),
nodeB.getChildNodes())) {
return false;
}
if (!isSubset(nodeA.getAttributes(),
nodeB.getAttributes())) {
return false;
}
return true;
}
static public boolean isSubset(Document
documentA, Document documentB) {
if
(!documentA.getDocumentElement().getNodeName()
.equals(documentB.getDocumentElement().getNodeName()))
{
return false;
}
if (!isSubset(documentA.getDocumentElement(),
documentB.getDocumentElement()))
{
return false;
}
return true;
}
static public Document
parseXML(String xmlSource) {
try {
DocumentBuilderFactory
factory = DocumentBuilderFactory
.newInstance();
DocumentBuilder
builder = factory.newDocumentBuilder();
return builder.parse(new InputSource(new
StringReader(xmlSource)));
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
static public boolean isSubset(String
xmlA, String xmlB) {
try {
return isSubset(parseXML(xmlA),
parseXML(xmlB));
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}