It would probably be better to use XML Schema to validate the document, but here is a programatic approach. Use XPath to select all the ids. Iterate over the ids, adding them to a Set. Before adding the current id, check to see if it already exists -- if it does, then you found a duplicate and can return that the document is invalid. Note that to get all the ids (all the way nested down), you have to change your XPath query expression.
import java.util.HashSet;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class RunValidateXmlIds {
public static void main(String[] args) throws ParserConfigurationException, XPathExpressionException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document d = db.newDocument();
if ( uniqueIds(d) ) {
System.out.println( " document is valid ");
} else {
System.out.println(" document is not valid ");
}
}
public static boolean uniqueIds(Document doc) throws XPathExpressionException {
XPathFactory xpf = XPathFactory.newInstance();
XPath xp = xpf.newXPath();
NodeList nl = (NodeList) xp.evaluate("/xml/mttag/@id", doc, XPathConstants.NODESET);
Set<String> allowedIds = new HashSet<String>();
for ( int i = 0; i < nl.getLength(); i++ ) {
Node n = nl.item(i);
Attr a = (Attr) n;
String attrValue = a.getNodeValue();
if ( allowedIds.contains(attrValue) ) {
// if we ever come here, that means there is a duplicate id
return false;
} else {
allowedIds.add(attrValue);
}
}
return true;
}
}
Bookmarks