How to dynamically assign attribute values in Xpath - java

I am trying to find the NodeList of the nodes containing any number of certain attributes in the XML file.
I can do the following and get the NodeList
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
DocumentBuilder db = dbf.newDocumentBuilder();
Document schDoc = db.newDocument();
InputStream schStream = new ByteArrayInputStream(sch.xml);
schDoc = db.parse(schStream)
schDoc.getDocumentElement().normalize();
XPath xpath1 = XPathFactory.newInstance().newXpath();
String expAttStr = "descendant-or-self::*[contains(#Name,'total_amt')]";
XPathExpression exprForTotalAmt = xpath1.compile(expAttStr);
NodeList totalAmtNodeList = (NodeList) exprForTotalAmt.evaluate(schDoc,XPathConstants.NODESET);
This is good.. But how can I loop and change the value of the attribute name. I tried the following and didn't work:
List<String> listOfItems= Arrays.asList("total_amt", "purchase_amt", "sales_amt");
long count = listOfItems.stream.distinct().count();
for(int i = 0; i<count; i++){
String expAttStr = "descendant-or-self::*[contains(#Name,listOfItems.get(i)]";
XPathExpression exprForTotalAmt = xpath1.compile(expAttStr);
NodeList totalAmtNodeList = (NodeList) exprForTotalAmt.evaluate(schDoc,XPathConstants.NODESET);
//some tasks
}
Would really appreciate it if anyone can point me in the right direction. Thanks.

Related

Add XML String as Node to Existing XML

I have an xml/mathml fragment in string like <msup><mn>2</mn><mn>6</mn></msup><mo>+</mo><msup><mn>2</mn><mn>7</mn></msup>
I want to replace an existing xml node with this string. I tried
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuild = docFactory.newDocumentBuilder();
Document doc = docBuild.parse(is); //is ==> Inputstream
XPath xpath = XPathFactory.newInstance().newXPath();
xpath.setNamespaceContext(new Namespace());
XPathExpression expr = xpath.compile(xPath); //xPath ==>XPath of parent node where the above is to be appended
Node node = (Node) expr.evaluate(doc, XPathConstants.NODE);
if (node.getChildNodes().item(0).getNodeName().equals("mml:math")) {
node.removeChild((node.getChildNodes().item(0)));
Element s= doc.createElement("mml:math");
s.setNodeValue("<msup><mn>2</mn><mn>6</mn></msup><mo>+</mo><msup><mn>2</mn><mn>7</mn></msup>");
node.appendChild(s);
}
Instead of using s.setNodeValue(), I used s.setTextContent() which fixed my problem.

use xpath to extract value from xml file with multiple namespace in java

I am trying to extract node value with multiple namespaces in java but not succeed. The xml file is like:
<ns26:start xmlns:ns26="http://www.tektronix.com/iris/isa/capture/start"
xmlns:ns31="http://www.tektronix.com/iris/isa/filters"
xmlns:ns13="http://www.tektronix.com/iris/isa/monitoredObjects"
xmlns:ns6="http://www.tektronix.com/iris/isa"
xmlns:ns10="http://www.tektronix.com/iris/isa/monNodeObjects"
xmlns:ns7="http://www.tektronix.com/iris/isa/capture/monitoredElements"
xmlns:ns11="http://www.tektronix.com/iris/isa/pointcodes"
xmlns:ns8="http://www.tektronix.com/iris/isa/capture/captureSession"
xmlns:ns2="http://www.tektronix.com/iris/isa/sessionSaveInfo"
xmlns:ns4="http://www.tektronix.com/iris/isa/customData"
xmlns:ns3="http://www.tektronix.com/iris/isa/manifest">
<ns6:Id>LAB:11300/isaclient;440</ns6:Id>
</ns26:start>
I want to extract Id with xpath local-name(). Expression like //*[local-name()='start']/*[local-name()='Id'] but didn't get any matched node. Please help to find issue here. Thanks
Add the java code here:
public static List<String> getXPathValueNamespace(String xml, String expression throws ParserConfigurationException, SAXException, IOException, XPathExpressionException
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder;
Document doc = null;
List<String> list = new ArrayList<String>();
builder = factory.newDocumentBuilder();
InputSource source = new InputSource(new StringReader(xml));
doc = builder.parse(source);
// Create XPathFactory object
XPathFactory xpathFactory = XPathFactory.newInstance();
// Create XPath object
XPath xpath = xpathFactory.newXPath();
XPathExpression expr = xpath.compile(expression);
NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);
for (int i = 0; i < nodes.getLength(); i++)
list.add(nodes.item(i).getNodeValue());
return list;
}
The expression //*[local-name()='start']/*[local-name()='Id'] works and for the example document one node should be contained in the result node list.
But you should use nodes.item(i).getTextContent() to retrieve the node content, since getNodeValue() returns null for element nodes.

How to get containing Node Name from xml namespace

I've got XPath of XML with it's structure like
<Statement xsi:type="conditionStatement">
<Id>CONDITION_0001</Id>
<Bounds>
<xValue>13</xValue>
<yValue>145</yValue>
<Height>402</Height>
<Width>513</Width>
</Bounds>
.........
.........
</statement>
Xpath takes me to xsi:type. But when I'm trying to get the name of node which is "statement" as expected, it's getting null.
My code for this is:-
nodeList = (NodeList) xPath.compile(xPathSrcFile).evaluate(xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++) {
nodeList.item(i).getParentNode();
}
For rest of the cases, code is working perfectly fine but when it gets to "xsi", code is throwing nullpointer exception.
Need some help to get node name from this.
try this
NodeList nodeList = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
InputStream inputStream= new FileInputStream(file);//xmlDocument as file
Reader reader = new InputStreamReader(inputStream,"ISO-8859-1");
InputSource is = new InputSource(reader);
is.setEncoding("ISO-8859-1");
Document doc = db.parse(is);
Element docEle = doc.getDocumentElement();
nodeList = docEle.getElementsByTagName("Statement");
1 Your XML file is incorrect:
it begins with Statement
and ends with /statement
2 you need this at root tag:
< root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
3 to get the name of you tag, use:
nodeList.item(i).getTagName();
4 what is your Xpath ?

XPath check for attribute and show the value

I need to check a bunch of .xml files for a specific permission, which is an attribute. If there is such a permission attribute i have to find out which value the attribute has.
this is my code which produces NullPointerExceptions:
public static void checkXmlPermissions(String path)
{
FileInputStream file;
try
{
file = new FileInputStream(new File(path));
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
//XPath initialisieren;
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(file);
XPath xPath = XPathFactory.newInstance().newXPath();
String expression ="//*[#permission]"; //Expression;
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
for (int i = 0; i < nodeList.getLength(); i++)
{
String match = nodeList.item(i).getFirstChild().getNodeValue();
System.out.println(match);
}
}
catch(Exception ex)
{
System.out.println(ex);
}
}
I guess my mistake is the NodeList but I canĀ“t find a solution by my own.
change:
String match = nodeList.item(i).getFirstChild().getNodeValue();
to:
String match = nodeList.item(i).getTextContent();

How to parse same name tag in xml using dom parser java?

How do you parse the same name tag in xml using dom parser java?
I have the following xml file that I would like to parse using the dom parser in java.
<?xml version="1.0"?>
<GameWorld>
<player>
<playerID>1</playerID>
<inventory>
<item>cards</item>
<item>notes</item>
<item>dice</item>
</inventory>
<position>50 50 10 60</position>
<room>offices</room>
</player>
<player>
<playerID>2</playerID>
<inventory>
<item>notes</item>
<item>dice</item>
<item>cards</item>
</inventory>
<position>10 10 10</position>
<room>security room</room>
</player>
</GameWorld>
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(f);
Element root = doc.getDocumentElement();
NodeList nodeList = doc.getElementsByTagName("player");
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
// do your stuff
}
but I'd rather suggest to use XPath
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(<uri_as_string>);
XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();
XPathExpression expr = xpath.compile("/GameWorld/player");
NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET);

Categories