import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Stack;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
public class XPPTest {
private final static Document doc;
static {
try {
final DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
doc = builder.newDocument();
} catch (ParserConfigurationException e) {
throw new RuntimeException(e);
}
}
/**
* @param args
* @throws IOException
* @throws XmlPullParserException
* @throws XmlPullParserException
* @throws TransformerException
* @throws FileNotFoundException
*/
public static void main(String[] args) throws XmlPullParserException, IOException, TransformerException {
new XPPTest();
}
public XPPTest() throws XmlPullParserException, IOException, TransformerException {
Reader fr = new FileReader(new File("/tmp/data.xml"));
XmlPullParserFactory parserFact = XmlPullParserFactory.newInstance();
XmlPullParser parser = parserFact.newPullParser();
parser.setInput(fr);
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
Iterator<Node> it = new LazyNodelistIterator("/Persons/Person", parser);
TransformerFactory tfactory = TransformerFactory.newInstance();
Transformer xform = tfactory.newTransformer();
Result xformResult = new StreamResult(System.out);
while(it.hasNext()) {
Node node = it.next();
Source src = new DOMSource(node);
xform.transform(src, xformResult);
System.out.println("\n----------------------------------------------");
}
}
private static class LazyNodelistIterator implements Iterator<Node> {
private final XmlPullParser parser;
private Node next;
private boolean searchedForNext = false;
private final Stack<String> currPath = new Stack<String>();
private final List<String> searchPath;
private final Stack<Node> nodeStack = new Stack<Node>();
private boolean match = false;
private LazyNodelistIterator(final String xpath, final XmlPullParser parser) {
this.parser = parser;
//Parse xpath expression
String[] ss = xpath.split("/");
searchPath = new ArrayList<String>(ss.length - 1);
for(int i = 1; i < ss.length; i++) {
searchPath.add(ss[i]);
}
}
public boolean hasNext() {
if(searchedForNext) return (next != null);
searchedForNext = true;
boolean foundNext = false;
while(!foundNext) {
int tokenType;
try {
tokenType = parser.nextToken();
} catch (XmlPullParserException e) {
throw new RuntimeException(e);
} catch (IOException e) {
throw new RuntimeException(e);
}
switch(tokenType) {
case XmlPullParser.START_TAG:
List<Attribute> attributes = new ArrayList<Attribute>(parser.getAttributeCount());
for(int i = 0; i < parser.getAttributeCount(); i++) {
Attribute a = new Attribute();
a.name = parser.getAttributeName(i);
a.namespace = parser.getAttributeNamespace(i);
a.value = parser.getAttributeValue(i);
attributes.add(a);
}
processStartTag(parser.getName(), parser.getNamespace(), attributes);
break;
case XmlPullParser.END_TAG:
foundNext = processEndTag();
break;
case XmlPullParser.TEXT:
processText(parser.getText());
break;
case XmlPullParser.CDSECT:
processCDSection(parser.getText());
break;
case XmlPullParser.END_DOCUMENT:
//reached the end of the document. no more matches possible
return false;
}
}
return foundNext;
}
private final void processText(final String data) {
if(match) {
Node text = doc.createTextNode(data);
nodeStack.peek().appendChild(text);
}
}
private final void processCDSection(final String data) {
if(match) {
Node cdata = doc.createCDATASection(data);
nodeStack.peek().appendChild(cdata);
}
}
private final void processStartTag(final String name, final String namespace, List<Attribute> attributes) {
currPath.push(name);
final boolean currNodeMatches = currNodeMatches();
Node n = null;
if(currNodeMatches || match) {
n = doc.createElementNS(namespace, name);
for(Attribute a : attributes) {
final Node attr = doc.createAttributeNS(a.namespace, a.name);
attr.setNodeValue(a.value);
n.getAttributes().setNamedItem(attr);
}
}
if(currNodeMatches) {
//start match
next = n;
nodeStack.push(next);
match = true;
return;
}
if(match) {
Node p = nodeStack.peek();
p.appendChild(n);
nodeStack.push(n);
}
}
private final boolean processEndTag() {
if(currNodeMatches()) {
nodeStack.pop();
match = false;
currPath.pop();
return true;
}
currPath.pop();
if(match) {
nodeStack.pop();
}
return false;
}
private final boolean currNodeMatches() {
return searchPath.equals((List<String>)currPath);
}
public Node next() {
if(searchedForNext) {
if(next == null) throw new NoSuchElementException();
searchedForNext = false;
return next;
}
if(hasNext()) {
searchedForNext = false;
return next;
}
throw new NoSuchElementException();
}
public void remove() {
throw new UnsupportedOperationException();
}
private static final class Attribute {
public String name;
public String namespace;
public String value;
}
}
}