I have an xml file like this:
<?xml version="1.0" encoding="UTF-8"?>
<ClOrdIDS><ClOrdID id="1"><Account>1005390</Account><Symbol>SAP</Symbol><SecurityID>4663789</SecurityID><SecurityExchange>XETR</SecurityExchange><Price>23.0</Price><Order_Type>Limit</Order_Type><Side>SELL</Side><Order_Quantity>0.001</Order_Quantity></ClOrdID><ClOrdID id="2"><Account>1005390</Account><Symbol>SAP</Symbol><SecurityID>4663789</SecurityID><SecurityExchange>XETR</SecurityExchange><Price>13.0</Price><Order_Type>Limit</Order_Type><Side>SELL</Side><Order_Quantity>0.001</Order_Quantity></ClOrdID><ClOrdID id="3"><Account>1005390</Account><Symbol>SAP</Symbol><SecurityID>4663789</SecurityID><SecurityExchange>XETR</SecurityExchange><Price>13.0</Price><Order_Type>Limit</Order_Type><Side>BUY</Side><Order_Quantity>0.001</Order_Quantity></ClOrdID><ClOrdID id="4"><Account>1005390</Account><Symbol>SAP</Symbol><SecurityID>4663789</SecurityID><SecurityExchange>XETR</SecurityExchange><Price>13.0</Price><Order_Type>Limit</Order_Type><Side>BUY</Side><Order_Quantity>0.001</Order_Quantity></ClOrdID><ClOrdID id="5"><Account>1005390</Account><Symbol>SAP</Symbol><SecurityID>4663789</SecurityID><SecurityExchange>XETR</SecurityExchange><Price>13.0</Price><Order_Type>Limit</Order_Type><Side>BUY</Side><Order_Quantity>0.001</Order_Quantity></ClOrdID><ClOrdID id="6"><Account>1005390</Account><Symbol>SAP</Symbol><SecurityID>4663789</SecurityID><SecurityExchange>XETR</SecurityExchange><Price>13.0</Price><Order_Type>Limit</Order_Type><Side>BUY</Side><Order_Quantity>0.001</Order_Quantity></ClOrdID><ClOrdID id="7"><Account>1005390</Account><Symbol>SAP</Symbol><SecurityID>4663789</SecurityID><SecurityExchange>XETR</SecurityExchange><Price>13.0</Price><Order_Type>Limit</Order_Type><Side>SELL</Side><Order_Quantity>0.001</Order_Quantity></ClOrdID></ClOrdIDS>
How can I extract the elements of child with ClOrdID id="3" ?
THANKS
You could do it this way
String xmlString = ...
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document doc = docBuilder.parse(xmlString);
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
String xpathExp = "/ClOrdIDS/ClOrdID[#id=\"3\"]";
NodeList childNodeList = (NodeList) xpath.evaluate(xpathExp, doc, XPathConstants.NODESET);
Since the tags on the question are JDOM, not DOM, you could use JDOM instead ;-) :
Document doc = new SaxBuilder().build(xmlFile);
XPathExpression<Element> xpe = XPathFactory.instance()
.compile("/ClOrdIDS/ClOrdID[#id=\"3\"]", Filters.element());
List<Element> idThrees = xpe.evaluate(doc);
Here is the code to do it in VTD-XML...
import com.ximpleware.*;
public class removeElement {
public static void main(String s[]) throws VTDException{
VTDGen vg = new VTDGen();
if (!vg.parseFile("input.xml", false))
return;
VTDNav vn = vg.getNav();
AutoPilot ap = new AutoPilot(vn);
ap.selectXPath("/ClOrdIDS/ClOrdID[#id='3']");
int i=0;
while((i=ap.evalXPath())!=-1){
}
}
}
Related
I want to query an XML via XPath. This XML has a namespace declared. I 've read that a NameContext on the XPath object has to be set and namespace awareness in the document factory should be enabled.
But the output in the getNamespaceURI(#String) method is never print. What I'm doing wrong?
String xpathStr = ... //some string
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder builder = dbf.newDocumentBuilder();
Document document = builder.parse(settlementFile);
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath(),
xpath.setNamespaceContext(new NamespaceContext() {
public String getNamespaceURI(String prefix) {
System.out.println("I'm here");
... //do some work
}
public String getPrefix(String uri) {
throw new UnsupportedOperationException();
}
public Iterator getPrefixes(String uri) {
throw new UnsupportedOperationException();
}
});
XPathExpression xpathExpression = xpath.compile(xpathStr);
String result = xpathExpression.evaluate(document);
Full exception stack:
Exception in thread "main" org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.
at org.apache.xerces.dom.CoreDocumentImpl.insertBefore(Unknown Source)
at org.apache.xerces.dom.NodeImpl.appendChild(Unknown Source)
at com.enniu.crawler.core.saxon.main(saxon.java:39)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
My Code:
public class saxon {
public static void main(String args[]) throws IOException, SAXException, ParserConfigurationException, XPathFactoryConfigurationException, XPathExpressionException {
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = null;
builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("test.html");
Document newDoc = builder.newDocument();
XPathFactory xpf = XPathFactoryImpl.newInstance(XPathConstants.DOM_OBJECT_MODEL);
XPath xPath = xpf.newXPath();
XPathExpression compile = xPath.compile("//div[not (contains(class, 'sss'))]");
Object result = compile.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for(int i = 0; i < nodes.getLength(); i++) {
Node copyNode = newDoc.importNode(nodes.item(i), true);
newDoc.appendChild(copyNode);// line 39
}
printXmlDocument(newDoc);
}
public static void printXmlDocument(Document document) {
DOMImplementationLS domImplementationLS =
(DOMImplementationLS) document.getImplementation();
LSSerializer lsSerializer =
domImplementationLS.createLSSerializer();
String string = lsSerializer.writeToString(document);
System.out.println(string);
}
}
test.html
<table>
<div>aa</div>
<div class="sss">ss</div>
<div>dd</div>
</table>
Because a valid http document can't have two roots. My code attempt to generate document like this:
<div>aa</div>
<div>dd</div>
There are two roots in the document so get the exception.
I want to fetch value of the node ServerVersion
<result>
<response id="27mSTG">
<routing>
<configs>
<linqmap.routing.RoutingServerConfig>
<SERVER_VERSION>1.0.388</SERVER_VERSION>
<PRE_PROCESSING_FILE_LOCATION/>
I have tried:
#Override
public void getProp(String prop) {
try {
final Document document = loadXMLFromString();
document.getElementById(??);
} catch (Exception e) {
e.printStackTrace();
}
}
private Document loadXMLFromString() throws Exception
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(xmlString));
return builder.parse(is);
}
But I’m not sure how to get the node’s ID.
Is there any easier way? Maybe even string parsing is enough?
There is no attribute Id defined in your xml element SERVER_VERSION. You can use document.getElementByTagName("SERVER_VERSION") to get the value.
Or use XPath to read the node:
final Document document = loadXMLFromString();
XPathFactory xpathfactory = XPathFactory.newInstance();
XPath xpath = xpathfactory.newXPath();
String xpathExpr="/result/SERVER_VERSION"; // assume result is the root node.
Node node=(Node)xPath.compile(xpathExpr).evaluate(document, XPathConstants.NODE);
I want to list some nodes from xml document by XPathFactory but I get plain text without xml nodes in return
My Xml Document is like this:
<?xml version="1.0" encoding="utf-8"?>
<journal>
<title>Hakim Research Journal</title>
<subject>Medical Sciences</subject>
<articleset>
<article>
<title>Challenges and Performance Improvement Approaches of Boards of Trustees of Universities of Medical Sciences and Health Services </title>
<content_type>Original</content_type>
</article>
<article>
<title> Risk Factors of Infant Mortality Rate in North East of Iran </title>
<content_type>Original</content_type>
</article>
</articleset>
</journal>
I want to have elements in return, like this:
<article>
<title>Challenges and Performance Improvement Approaches of Boards of Trustees of Universities of Medical Sciences and Health Services in Iran </title>
<content_type>Original</content_type>
</article>
<article>
<title> Risk Factors of Infant Mortality Rate in North East</title>
<content_type>Original</content_type>
</article>
My Code implementation is:
String result="";
File xmlDocument = new File("e://journal_last.xml");
InputSource inputSource = new InputSource(new FileInputStream(xmlDocument));
XPathFactory factory=XPathFactory.newInstance();
XPath xPath=factory.newXPath();
XPathExpression articleset;
articleset = xPath.compile("/journal/articleset/)");
result = articleset.evaluate(inputSource);
System.out.println(result);
but it just returns plain text of nodes without node tags !
The output is:
Challenges and Performance Improvement Approaches of Boards of Trustees of Universities of Medical Sciences and Health Services
Original
Risk Factors of Infant Mortality Rate in North East
Original
Would you please help me ?
I appreciate any help.
You can evaluate the XPath on a Document to get the NodeList of the articles and than write the NodeList as xml.
public class Main {
public static void main(String[] args) throws Exception {
File xmlDocument = new File("e://journal_last.xml");
FileInputStream xmlInputStream = new FileInputStream(xmlDocument);
Document doc = parseDocument(new InputSource(xmlInputStream));
NodeList articleList = evaluateXPath(doc, "/journal/articleset",
NodeList.class);
String xmlString = writeXmlString(articleList);
System.out.println(xmlString);
}
private static Document parseDocument(InputSource inputSource)
throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory
.newInstance();
DocumentBuilder docBuilder = documentBuilderFactory
.newDocumentBuilder();
Document doc = docBuilder.parse(inputSource);
return doc;
}
#SuppressWarnings("unchecked")
private static <T> T evaluateXPath(Document doc, String xpath,
Class<T> resultType) throws XPathExpressionException {
QName returnType = resolveReturnType(resultType);
XPathFactory factory = XPathFactory.newInstance();
XPath xPath = factory.newXPath();
XPathExpression xpathExpression = xPath.compile(xpath);
Object resultObject = xpathExpression.evaluate(doc, returnType);
return (T) resultObject;
}
private static QName resolveReturnType(Class<?> clazz) {
if (NodeList.class.equals(clazz)) {
return XPathConstants.NODESET;
} else {
throw new UnsupportedOperationException("Not implemented yet");
}
}
private static String writeXmlString(NodeList nodeList)
throws TransformerConfigurationException,
TransformerFactoryConfigurationError, TransformerException {
StreamResult streamResult = new StreamResult(new StringWriter());
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
for (int i = 0; i < nodeList.getLength(); i++) {
Node articleListItem = nodeList.item(i);
DOMSource source = new DOMSource(articleListItem);
transformer.transform(source, streamResult);
}
String xmlString = streamResult.getWriter().toString();
return xmlString;
}
}
this is my XML file :
<sitemesh>
<mapping path="/editor/tempPage/**" exclude="true"/>
<mapping decorator="/WEB-INF/views/decorators/detailstheme.jsp"
path="/*" exclude="false" />
</sitemesh>
I want list of mapping node with their attribute values.
this should be done using Xpath.
my xpath expression is :
expr = xpath.compile("/sitemesh/mapping");
but i am getting null in nodelist.
this is my code:
Map<String,String> map=new HashMap<String, String>();
// reading xml file
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
Document doc = null;
XPathExpression expr = null;
try {
builder = factory.newDocumentBuilder();
// creating input stream
doc = builder.parse(file);
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
expr = xpath.compile("//mapping");
} catch (Exception e) {
LOG.error("some exception message", e);
}
//------------------------------------------------------------------------
NodeList attributeElements = null;
try {
attributeElements =(NodeList)expr.evaluate(doc, XPathConstants.NODE);
} catch (XPathExpressionException e) {
LOG.error("some exception message", e);
}
System.out.println("lenght:"+attributeElements.getLength());
for (int i = 0; i < attributeElements.getLength(); i++) {
Node node=attributeElements.item(i);
System.out.println("node:"+node.getNodeValue());
NamedNodeMap attrs = node.getAttributes();
for(i = 0 ; i<attrs.getLength() ; i++) {
Attr attribute = (Attr)attrs.item(i);
System.out.println("Node Attributes : " + attribute.getName()+" = "+attribute.getValue());
}
}
//-------------------------------------------------------------------------
// writing xml file
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer;
try {
transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(file);// creating output
// stream
transformer.transform(source, result);
} catch (Exception e) {
LOG.error("some exception message", e);
}
return map;
i am getting null for attributeElements
i want to show values of path,decorator and exclude on JSP page.But i am unable to get list of node through xpath expression.
I want solution for reading mapping node element in Xpath.
[edit] /sitemesh/mapping also works .
The issue here is that you evaluating the express for XPathConstants.NODE while the nodeList maps to XPathConstants.NODESET. please refer below link.
http://docs.oracle.com/javase/1.5.0/docs/api/javax/xml/xpath/XPathConstants.html#NODESET
Added sample code for illustration purpose only:
public void testXpathExpr(){
String testXML = "<sitemesh><mapping path=\"/editor/tempPage/**\" exclude=\"true\"/><mapping decorator=\"/WEB-INF/views/decorators/detailstheme.jsp\" path=\"/*\" exclude=\"false\" /></sitemesh>";
NodeList nodeList = getNodeList(testXML);
}
private NodeList getNodeList(String xml) throws SAXException, IOException, ParserConfigurationException, XPathExpressionException {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = docFactory.newDocumentBuilder();
document = builder.parse(new ByteArrayInputStream( xml.getBytes() ) );
XPathExpression exprPath = xpath.compile(xpathExpr);
NodeList nodeList = (NodeList) exprPath.evaluate(document, XPathConstants.NODESET);;
return nodeList;
}
Hope this helps!
Your xpath works perfectly for me. Below is the sample code:
public class Parser {
public static void main(String[] args) throws Exception, Exception {
final DocumentBuilderFactory factory = DocumentBuilderFactory
.newInstance();
final DocumentBuilder builder = factory.newDocumentBuilder();
final Document doc = builder.parse("src/sitemesh.xml");
final XPathFactory xPathfactory = XPathFactory.newInstance();
final XPath xpath = xPathfactory.newXPath();
final XPathExpression expr = xpath.compile("/sitemesh/mapping");
Object node = expr.evaluate(doc, XPathConstants.NODE);
System.out.println(node);
}
}
sitemesh.xml contains your sample input.