Edit an xml file element using dom - java

Please tell me what I'm doing wrong.
I work with javafx and by clicking on the button, when the listview element is selected, I pass an object of the Country class to the editing method, but the xml file is not being edited, what is the problem?
I attached an xml file, a broken edit function and a working delete function. I think it's about the setContext I'm calling? But I'm not sure
Xml file:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<CountrysList lastId="3">
<Country id="1">
<name>Russia</name>
<continent>Eurasia</continent>
<area>17125191</area>
<population>145557576</population>
<capital>Moscow</capital>
</Country>
<Country id="2">
<name>Russia</name>
<continent>Eurasia</continent>
<area>17125191</area>
<population>145557576</population>
<capital>Moscow</capital>
</Country>
<Country id="3">
<name>Russia</name>
<continent>Eurasia</continent>
<area>17125191</area>
<population>145557576</population>
<capital>Moscow</capital>
</Country>
Element search function:
public Element findCountry(Document document, int id) {
NodeList countries = document.getElementsByTagName("Country");
Element currentCountry = null;
int i = 0;
while(i < countries.getLength() && currentCountry == null){
Node node = countries.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE){
Element element = (Element) node;
if(String.valueOf(id).equals(element.getAttribute("id"))){
currentCountry = element;
}
}
i++;
}
return currentCountry;
}
Broken editing function:
public void redact(Country country) throws ParserConfigurationException, IOException, SAXException, TransformerException {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document document = docBuilder.parse(path);
Element currentCountry = findCountry(document, country.getId());
if(currentCountry != null){
NodeList children = currentCountry.getChildNodes();
for (int j=0; j < children.getLength(); j++){
Node node = children.item(j);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
switch (element.getTagName()){
case "name":
element.setTextContent(country.getName());
break;
case "continent":
element.setTextContent(country.getContinent());
break;
case "area":
element.setTextContent(String.valueOf(country.getArea()));
break;
case "population":
element.setTextContent(String.valueOf(country.getPopulation()));
break;
case "capital":
element.setTextContent(country.getCapital());
break;
}
}
}
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(new DOMSource(document), new StreamResult(path));
}
}
Working deletion function:
public void delete(Country country) throws ParserConfigurationException, IOException, SAXException, TransformerException {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document document = docBuilder.parse(path);
Element rootElement = document.getDocumentElement();
Element currentCountry = findCountry(document, country.getId());
if(currentCountry != null){
rootElement.removeChild(currentCountry);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(new DOMSource(document), new StreamResult(path));
}
}

I found the mistake.Everything is really like that, I forgot to create a new instance of the class with the changed fields and passed it with the previous ones, so everything worked

Related

Get second row xml using first rows text value java

public void loadSettings() {
try {
File inputFile = new File("data.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("Setting");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nList.item(temp);
NodeList VariableName = eElement.getElementsByTagName("VariableName");
NodeList VariableValue = eElement.getElementsByTagName("VariableValue");
System.out.println(VariableName.item(0).getTextContent());
if (VariableName.item(0).hasChildNodes()) {
}
// txtBookmarkUrl.setText(bookMarkUrl);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
I want to make a function that gets second part of the xml in settings elements. I want the function to return a result so that i can assign it to textfield default value when the swing GUI starts. The function should take let's say 'isDecaptcher' variable name and return '0' VariableValue.
<Bookmark>
<Setting>
<VariableName>isDeathbycaptcha</VariableName>
<VariableValue>0</VariableValue>
</Setting>
<Setting>
<VariableName>isDecaptcher</VariableName>
<VariableValue>0</VariableValue>
</Setting>
<Setting>
<VariableName>isExpertdecoders</VariableName>
<VariableValue>0</VariableValue>
</Setting>
<Setting>
<VariableName>ManualCaptcha</VariableName>
<VariableValue>1</VariableValue>
</Setting>
</Bookmark>
public void loadSettings(String variableName) {
try {
File inputFile = new File("data.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(inputFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("Setting");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nList.item(temp);
NodeList VariableName = eElement.getElementsByTagName("VariableName");
NodeList VariableValue = eElement.getElementsByTagName("VariableValue");
if (VariableName.item(0).getTextContent().equalsIgnoreCase(variableName)) {
String txtBookmarkUrlValue = VariableValue.item(0).getLastChild().getTextContent();
System.out.println(txtBookmarkUrlValue);
txtBookmarkUrl.setText(txtBookmarkUrlValue);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
This works, But if you have more robust answers you can share.
First of all create an Object wich will represent your settings. The case is to reuse it's values in whole app. I assume that you will use it only once at the beginning and settings will not change. Singleton pattern would fit there.
final class Settings{
private static volatile Settings instance = null;
private boolean _isDeathByCaptcha;
private boolean _manualCaptcha;
...
//getters & setters
public boolean isDeathByCaptcha(){
return _isDeathByCaptcha;
}
public void setIsDeathByCaptcha(boolean isDeathByCaptcha){
this._isDeathByCaptcha = isDeathByCaptcha;
}
private Settings(){}
public static Settings getInstance(){
if(instance == null){
synchronized (Settings.class) {
if (instance == null) {
instance = new Settings();
}
}
}
return instance;
}
}
After that you can call Settings.getInstance().isDeathByCaptcha(); to get your value. Of course you need to set it earlier with setter.

XPathFactory return xml document

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

Reading XML for specific nodes

Let's say I have an XML like below
<?xml version="1.0" encoding="UTF-8"?>
<Data>
<CreditCards>
<Visa>
<Name>visaname</Name>
<Number>4265787654344445</Number>
<ExpMonth>05</ExpMonth>
<ExpYear>2017</ExpYear>
<CVV>123</CVV>
</Visa>
<Master>
<Name>mastername</Name>
<Number>5678787654344445</Number>
<ExpMonth>05</ExpMonth>
<ExpYear>2015</ExpYear>
<CVV>123</CVV>
</Master>
</CreditCards>
</Data>
Let's say I have a method like below
public void readData(String nodeName) {
//Code here
}
So when I use this method like
readData("Visa");
I should be printing all the child nodes and corresponding values. The output should look like this
Name = visaname
Number = 4265787654344445
ExpMonth = 05
ExpYear = 2017
CVV = 123
And
if I have an xml like below
<Data>
<employee>
<firstname>test1</firstname>
<lastname>lasttest</lastname>
</employee>
</data>
and If my method is like below
public void readData2(String nodeName) {
//Code here
}
when I use the method
readData2("firstname");
it should print the following
test1
Is it really possible? I tried using JDOM2 API but couldn't get it working. What would be the ideal way to achieve both the results? Thanks!!
Code I'm trying
public void readXMLData(String filePath) {
File xmlFile = new File(filePath);
Map<String,String> parametersMap = new HashMap<String,String>();
try {
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(xmlFile);
doc.getDocumentElement().normalize();
//Root Element
System.out.println("Root element : " + doc.getDocumentElement().getNodeName());
NodeList nodeLst = doc.getElementsByTagName("Visa");
System.out.println("----------Information of Visa Card----------");
Node node = nodeLst.item(0);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
System.out.println("Child nodes : "+element.getChildNodes());
}
}
catch(Exception e) {
e.printStackTrace();
}
}

Get a specific child name in an XML file

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){
}
}
}

Reading List of Node using Xpath

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.

Categories

Resources