XPath生成もどきもどきもどき 2008/09/05

Javaです。
既に出来上がったXMLをパースするプログラムを書く際に、必要な箇所だけをXPathとかでとりたいなぁというときに、パスが既に存在するXMLから生成できたら便利かなぁ、というわけで作成。

不完全だけど、パスの雰囲気はでてるかな。

package xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Set;
import java.util.TreeSet;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class TestXPathGenUtils {

public static void main(String[] args) throws URISyntaxException,
FileNotFoundException, SAXException, IOException,
ParserConfigurationException {

URL url = TestXPathGenUtils.class.getResource("test.xml");

File file = new File(url.toURI());
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();

Set<String> set = new TreeSet<String>();
XPathGenUtils.generatePath(builder.parse(new InputSource(new FileInputStream(file))), set);

for (String s : set) {
System.out.println(s);
}

}

}


package xml;

import java.util.Set;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* <p>
* XPath生成もどき
* </p>
*
* @author nakawaka
*
*/
public abstract class XPathGenUtils {

public static void generatePath(Document document, Set<String> set) {
innerGeneratePath(document.getDocumentElement(), set);
}

public static void generatePath(Element element, Set<String> set) {
innerGeneratePath(element, set);
}

static void innerGeneratePath(Node node, Set<String> set) {
switch (node.getNodeType()) {

case Node.DOCUMENT_NODE:
generatePath(((Document) node).getDocumentElement(), set);
return;
case Node.ELEMENT_NODE:

Element element = (Element) node;

NamedNodeMap namedNodeMap = element.getAttributes();
for (int i = 0; i < namedNodeMap.getLength(); ++i) {
innerGeneratePath(namedNodeMap.item(i), set);
}

NodeList nodeList = element.getChildNodes();
for (int i = 0; i < nodeList.getLength(); ++i) {
innerGeneratePath(nodeList.item(i), set);
}

return;
case Node.TEXT_NODE:
set.add(p(node, new StringBuilder()));
return;
case Node.CDATA_SECTION_NODE:
return;
case Node.ENTITY_REFERENCE_NODE:
return;
case Node.ATTRIBUTE_NODE:
set.add(p(node, new StringBuilder()));
return;
}

}

public static String p(Node node, StringBuilder builder) {

// System.out.println(parent.getNodeName());

if (node.getNodeType() == Node.DOCUMENT_NODE)
return builder.toString();

switch (node.getNodeType()) {
case Node.TEXT_NODE:
builder.insert(0, "/" + "text()");
return p(node.getParentNode(), builder);
case Node.CDATA_SECTION_NODE:
break;
case Node.ENTITY_REFERENCE_NODE:
break;
case Node.ATTRIBUTE_NODE:
builder.insert(0, "/@" + node.getNodeName() + "");
Attr attr = (Attr) node;
return p(attr.getOwnerElement(), builder);
}

builder.insert(0, "/" + node.getNodeName());
return p(node.getParentNode(), builder);
}
}


出来上がったパスは下のコードで実行
package xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

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.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class TestReadXml {

public static void main(String[] args) throws URISyntaxException,
ParserConfigurationException, FileNotFoundException, SAXException,
IOException, XPathExpressionException {

URL url = TestReadXml.class.getResource("test.xml");

File file = new File(url.toURI());
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document document = builder.parse(new InputSource(new FileInputStream(
file)));

System.out.println(string(document, compile("パステストここに入れる")));
}

static final XPath xpath = XPathFactory.newInstance().newXPath();

static XPathExpression compile(String expression)
throws XPathExpressionException {
return xpath.compile(expression);
}

static String string(Document root, XPathExpression expr)
throws XPathExpressionException {
return (String) expr.evaluate(root, XPathConstants.STRING);
}

}

: