xml search element by id - java

Can we search a element by id in xml file using dom parser, for example :
<root>
<context id="one">
<entity>
<identifier>new one</identifier>
</entity>
</context>
<context id="two">
<entity>
<identifier>second one</identifier>
</entity>
</context>
</root>
I want a node with id = "one", my code
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document document = docBuilder.parse(new File("filename.xml"));
Element ele = document.getElementById("one");
return null,
is there any other way?

From the documentation for Document.getElementById
Note: Attributes with the name "ID" or "id" are not of type ID unless so defined.
The problem is the Document doesn't know that an attribute called id is an identifier unless you tell it. You need to set a schema on the DocumentBuilderFactory before you call newDocumentBuilder. That way the DocumentBuilder will be aware of the element types.
In the schema you will need something like this in the appropriate place:
<xs:attribute name="id" type="xs:ID"/>

You could use the javax.xml.xpath APIs in the JDK/JRE to find the element by XPath.
Example
import java.io.File;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import org.w3c.dom.*;
public class Demo {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
Document document = docBuilder.parse(new File("filename.xml"));
XPathFactory xpathFactory = XPathFactory.newInstance();
XPath xpath = xpathFactory.newXPath();
Element element = (Element) xpath.evaluate("//*[#id='one']", document, XPathConstants.NODE);
}
}

You could instead use a third party library like Jsoup that does the job rather quite well.
File input = new File("/tmp/input.xml");
Document doc = Jsoup.parse(input, "UTF-8", "test");
And then you could use something like this:
doc.select("context#id=one")
Does that answer your question?

try and use XML - Xpath expression it is very easy
File fXmlFile = new File("filePath");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
doc.getDocumentElement().normalize();
System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
String expression;
Node node;
// 1. elements with id '1'
expression = "//context[#id='one']";
node = (Node ) xpath.evaluate(expression, doc, XPathConstants.NODE);

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.

How to create tag with namespace prefix

I am trying to add a prefix to a tag to represent a particular namespace - as can be seen below
String envelopePrefix = "omgEnv";
String businessPrefix = "omgBS";
String namespaceURI = "http://www.w3.org/2000/xmlns/";
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("OmgeoMessageContainer");
rootElement.setAttributeNS(namespaceURI, "xmlns:" + envelopePrefix, "http://www.omgeo.com/schema/v1.0/envelope");
rootElement.setAttributeNS(namespaceURI, "xmlns:" + businessPrefix, "http://www.omgeo.com/schema/v1.0/BusinessServices");
doc.appendChild(rootElement);
Element messageParties = doc.createElementNS(namespaceURI, envelopePrefix + ":MessageParties");
rootElement.appendChild(messageParties);
Unfortunately my messageParties element is failing with the following error -
org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create
or change an object in a way which is incorrect with regard to
namespaces.
How are you supposed to prefix a tag with the correct namespace definition? Event the setPrefix method throws the same error.
Thanks
I do not think you can decide the prefix for a namespace element while generating XML. I did not see any such option in the JavaDocs. To create element with namespace this should be the modification.
String namespaceURI = "http://www.w3.org/2000/xmlns/";
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElementNS(namespaceURI, "OmgeoMessageContainer");
doc.appendChild(rootElement);
Element messageParties = doc.createElementNS(namespaceURI, "MessageParties");
rootElement.appendChild(messageParties);
This will generate the XML with auto decided prefix for the namespaces.

DOM to XML in JAVA is not working

I have written the following code
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
// Unniversity tag
Element rootElement = doc.createElement("university");
// Unniversity attrs
Attr uniName = doc.createAttribute("name");
uniName.setNodeValue(university.name);
Attr uniLogo = doc.createAttribute("logo");
uniLogo.setNodeValue(university.pathToLogo);
Attr uniMission = doc.createAttribute("mission");
uniMission.setNodeValue(university.mission);
Attr uniVision = doc.createAttribute("vision");
uniVision.setNodeValue(university.vision);
rootElement.setAttributeNode(uniName);
rootElement.setAttributeNode(uniLogo);
rootElement.setAttributeNode(uniMission);
rootElement.setAttributeNode(uniVision);
While debugging when I check the value of doc I found following
doc = (com.sun.org.apache.xerces.internal.dom.DocumentImpl) [#document: null]
What am I doing wrong? I followed this.
In your code you have not set the contents of the document. You should add the following:
document.appendChild(rootElement);
To confirm that the document contains the XML structure you can print the following statement:\
System.out.println(document.getDocumentElement());
This will print [university : null]
Well I was making a silly mistake i.e. I donot bind/add the rootElement with doc
Updated Code:
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.newDocument();
// Unniversity tag
Element rootElement = doc.createElement("university");
doc.appendChild(rootElement); // I forgot to add this statement
// Unniversity attrs
Attr uniName = doc.createAttribute("name");
uniName.setNodeValue(university.name);
Attr uniLogo = doc.createAttribute("logo");
uniLogo.setNodeValue(university.pathToLogo);
Attr uniMission = doc.createAttribute("mission");
uniMission.setNodeValue(university.mission);
Attr uniVision = doc.createAttribute("vision");
uniVision.setNodeValue(university.vision);
rootElement.setAttributeNode(uniName);
rootElement.setAttributeNode(uniLogo);
rootElement.setAttributeNode(uniMission);
rootElement.setAttributeNode(uniVision);

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);

Getting parent node content in xml file by java

In XML file a Parent tag has multiple child tag, with content inside.
I need the Parent tag info only,
how to get that:
i.e.,
<main>**Name**
<names>**Harish**</names>
<names2>**Mathi**</names>
</main>
Here i need only "Name". I no need "Harish","Mathi"...
in this case what i have to include in JAVA code...
You can do using XPath:
main/text()
UPDATE:
Example:
DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
domFactory.setNamespaceAware(true);
DocumentBuilder builder = domFactory.newDocumentBuilder();
Document doc = builder.parse("sample.xml");
XPath xpath = XPathFactory.newInstance().newXPath();
XPathExpression expr = xpath.compile("main/text()");
Object result = expr.evaluate(doc, XPathConstants.STRING);
System.out.println(result.toString());
OUTPUT:
**Name**

Categories