Search...
FAQs
Subscribe
Pie
FAQs
Recent topics
Flagged topics
Hot topics
Best topics
Search...
Search within Wiki
Search Coderanch
Advance search
Google search
Register / Login
Win a copy of
OCP Oracle Certified Professional Java SE 21 Developer (Exam 1Z0-830) Java SE 17 Developer (Exam 1Z0-829) Programmer’s Guide
this week in the
Programmer Certification
forum!
Bookmark Topic
Watch Topic
programming forums
Java
Mobile
Certification
Databases
Caching
Books
Engineering
Micro Controllers
OS
Languages
Paradigms
IDEs
Build Tools
Frameworks
Application Servers
Open Source
This Site
Careers
Other
Pie Elite
all forums
this forum made possible by our volunteer staff, including ...
Marshals:
Tim Cooke
Campbell Ritchie
paul wheaton
Ron McLeod
Devaka Cooray
Sheriffs:
Jeanne Boyarsky
Liutauras Vilda
Paul Clapham
Saloon Keepers:
Tim Holloway
Carey Brown
Piet Souris
Bartenders:
Forum:
Wiki
SAX Create XPath
posted 9 years ago
Number of slices to send:
Optional 'thank-you' note:
Send
This class uses SAX to parse an XML file and creates XPath expressions for each element encountered. As is mentioned in the code, the algorithm is not correct in all circumstances. The problem was discussed
in this Saloon thread
.
import java.io.File; import java.util.HashMap; import java.util.Map; import java.util.Stack; import javax.xml.parsers.*; import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; /** * SAX handler that creates and prints XPath expressions for each element encountered. * * The algorithm is not infallible, if elements appear on different levels in the hierarchy. * Something like the following is an example: * - <elemA/> * - <elemA/> * - <elemB/> * - <elemA/> * - <elemC> * - <elemB/> * - </elemC> * * will report * * //elemA[0] * //elemA[1] * //elemB[0] * //elemA[2] * //elemC[0] * //elemC[0]/elemB[1] (this is wrong: should be //elemC[0]/elemB[0] ) * * It also ignores namespaces, and thus treats <foo:elemA> the same as <bar:elemA>. */ public class SAXCreateXPath extends DefaultHandler { // map of all encountered tags and their running count private Map<String, Integer> tagCount; // keep track of the succession of elements private Stack<String> tags; // set to the tag name of the recently closed tag String lastClosedTag; /** * Construct the XPath expression */ private String getCurrentXPath() { String str = "//"; boolean first = true; for (String tag : tags) { if (first) str = str + tag; else str = str + "/" + tag; str += "["+tagCount.get(tag)+"]"; first = false; } return str; } @Override public void startDocument() throws SAXException { tags = new Stack(); tagCount = new HashMap<String, Integer>(); } @Override public void startElement (String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { boolean isRepeatElement = false; if (tagCount.get(localName) == null) { tagCount.put(localName, 0); } else { tagCount.put(localName, 1 + tagCount.get(localName)); } if (lastClosedTag != null) { // an element was recently closed ... if (lastClosedTag.equals(localName)) { // ... and it's the same as the current one isRepeatElement = true; } else { // ... but it's different from the current one, so discard it tags.pop(); } } // if it's not the same element, add the new element and zero count to list if (! isRepeatElement) { tags.push(localName); } System.out.println(getCurrentXPath()); lastClosedTag = null; } @Override public void endElement (String uri, String localName, String qName) throws SAXException { // if two tags are closed in succession (without an intermediate opening tag), // then the information about the deeper nested one is discarded if (lastClosedTag != null) { tags.pop(); } lastClosedTag = localName; } public static void main (String[] args) throws Exception { if (args.length < 1) { System.err.println("Usage: SAXCreateXPath <file.xml>"); System.exit(1); } // Create a JAXP SAXParserFactory and configure it SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setNamespaceAware(true); spf.setValidating(false); // Create a JAXP SAXParser SAXParser saxParser = spf.newSAXParser(); // Get the encapsulated SAX XMLReader XMLReader xmlReader = saxParser.getXMLReader(); // Set the ContentHandler of the XMLReader xmlReader.setContentHandler(new SAXCreateXPath()); String filename = args[0]; String path = new File(filename).getAbsolutePath(); if (File.separatorChar != '/') { path = path.replace(File.separatorChar, '/'); } if (!path.startsWith("/")) { path = "/" + path; } // Tell the XMLReader to parse the XML document xmlReader.parse("file:"+path); } }
CategoryCodeSamples
Bookmark Topic
Watch Topic
New Topic
Boost this thread!
Similar Threads
problem in getting xpath of each node.
SAX problem
Reading XML file to populate text fields
XML as calculator input
Getting Node Value using SAX
More...