package org.jvnet.jaxb2_commons.xpath_tracker;
import org.xml.sax.helpers.XMLFilterImpl;
import org.xml.sax.XMLReader;
import org.xml.sax.ContentHandler;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.XMLFilter;
import java.util.Stack;
/**
* {@link XMLFilter} that monitors the infoset that flows through it,
* and provide a capability to {@link #getXPath() compute the XPath to the current element}.
*
* <p>
* In context of JAXB, this can be used to report error location by using XPath.
*
* @author Kohsuke Kawaguchi
*/
public class XPathTracker extends XMLFilterImpl {
private final Stack<Histgram> histgrams = new Stack<Histgram>();
public XPathTracker() {
super();
}
public XPathTracker(XMLReader parent) {
super(parent);
}
public XPathTracker(ContentHandler contentHandler) {
setContentHandler(contentHandler);
}
public void startDocument() throws SAXException {
super.startDocument();
histgrams.clear();
histgrams.push(new Histgram());
}
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
super.startElement(uri, localName, qName, atts);
histgrams.peek().update(uri,localName,qName);
histgrams.push(new Histgram());
}
public void endElement(String uri, String localName, String qName) throws SAXException {
super.endElement(uri, localName, qName);
histgrams.pop();
}
/**
* Gets the XPath to the current element.
*/
public String getXPath() {
StringBuilder buf = new StringBuilder();
for (Histgram h : histgrams) {
h.appendPath(buf);
}
return buf.toString();
}
}