I have xml documents that look like this:
<?xml version="1.0"?>
<root>
<success>true</success>
<note>
<note_id>32219</note_id>
<the_date>1336763490</the_date>
<member_id>108649</member_id>
<area>6</area>
<note>Note 123123123</note>
</note>
<note>
<note_id>33734</note_id>
<the_date>1339003652</the_date>
<member_id>108649</member_id>
<area>1</area>
<note>This is another note.</note>
</note>
<note>
<note_id>49617</note_id>
<the_date>1343050791</the_date>
<member_id>108649</member_id>
<area>1</area>
<note>this is a 3rd note.</note>
</note>
</root>
I would like to take that document, and get all of the <note> tags and convert them to a string, then pass them to my XML class and place the XML class into an array list. I hope that makes sense. So Here is the method that I am trying to use to get all of the <note> tags.
public ArrayList<XML> getNodes(String root, String name){
ArrayList<XML> elList = new ArrayList<>();
NodeList nodes = doc.getElementsByTagName(root);
for(int i = 0; i < nodes.getLength(); i++){
Element element = (Element)nodes.item(i);
NodeList nl = element.getElementsByTagName(name);
for(int c = 0; c < nl.getLength(); c++){
Element e = (Element)nl.item(c);
String xmlStr = this.nodeToString(e);
XML xml = new XML();
xml.parse(xmlStr);
elList.add(xml);
}
}
return elList;
}
private String nodeToString(Node node){
StringWriter sw = new StringWriter();
try{
Transformer t = TransformerFactory.newInstance().newTransformer();
t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
t.transform(new DOMSource(node), new StreamResult(sw));
}catch(TransformerException te){
System.out.println("nodeToString Transformer Exception");
}
return sw.toString();
}
So, my question is, how can I get each <note> tag as a string? With the code I have now all I get back is null for String xmlStr = e.getNodeValue();.
Edit
I edited my main code, this seems to work.
Updated after clarification
You can find all the <note> elements using XPath.
This will allow you to isolate each node simply. You can then create a new document, based on the found nodes and transform it back to string
public class TestXML01 {
public static void main(String[] args) {
String xml = "<?xml version=\"1.0\"?>";
xml += "<root>";
xml += "<success>true</success>";
xml += "<note>";
xml += "<note_id>32219</note_id>";
xml += "<the_date>1336763490</the_date>";
xml += "<member_id>108649</member_id>";
xml += "<area>6</area>";
xml += "<note>Note 123123123</note>";
xml += "</note>";
xml += "<note>";
xml += "<note_id>33734</note_id>";
xml += "<the_date>1339003652</the_date>";
xml += "<member_id>108649</member_id>";
xml += "<area>1</area>";
xml += "<note>This is another note.</note>";
xml += "</note>";
xml += "<note>";
xml += "<note_id>49617</note_id>";
xml += "<the_date>1343050791</the_date>";
xml += "<member_id>108649</member_id>";
xml += "<area>1</area>";
xml += "<note>this is a 3rd note.</note>";
xml += "</note>";
xml += "</root>";
ByteArrayInputStream bais = null;
try {
bais = new ByteArrayInputStream(xml.getBytes());
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
Document xmlDoc = builder.parse(bais);
Node root = xmlDoc.getDocumentElement();
XPathFactory xFactory = XPathFactory.newInstance();
XPath xPath = xFactory.newXPath();
XPathExpression xExpress = xPath.compile("/root/note");
NodeList nodes = (NodeList) xExpress.evaluate(root, XPathConstants.NODESET);
System.out.println("Found " + nodes.getLength() + " note nodes");
for (int index = 0; index < nodes.getLength(); index++) {
Node node = nodes.item(index);
Document childDoc = builder.newDocument();
childDoc.adoptNode(node);
childDoc.appendChild(node);
System.out.println(toString(childDoc));
}
} catch (Exception exp) {
exp.printStackTrace();
} finally {
try {
bais.close();
} catch (Exception e) {
}
}
}
public static String toString(Document doc) {
String sValue = null;
ByteArrayOutputStream baos = null;
OutputStreamWriter osw = null;
try {
baos = new ByteArrayOutputStream();
osw = new OutputStreamWriter(baos);
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.setOutputProperty(OutputKeys.INDENT, "yes");
tf.setOutputProperty(OutputKeys.METHOD, "xml");
tf.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
DOMSource domSource = new DOMSource(doc);
StreamResult sr = new StreamResult(osw);
tf.transform(domSource, sr);
osw.flush();
baos.flush();
sValue = new String(baos.toByteArray());
} catch (Exception exp) {
exp.printStackTrace();
} finally {
try {
osw.close();
} catch (Exception exp) {
}
try {
baos.close();
} catch (Exception exp) {
}
}
return sValue;
}
}
This now outputs...
Found 3 note nodes
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<note>
<note_id>32219</note_id>
<the_date>1336763490</the_date>
<member_id>108649</member_id>
<area>6</area>
<note>Note 123123123</note>
</note>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<note>
<note_id>33734</note_id>
<the_date>1339003652</the_date>
<member_id>108649</member_id>
<area>1</area>
<note>This is another note.</note>
</note>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<note>
<note_id>49617</note_id>
<the_date>1343050791</the_date>
<member_id>108649</member_id>
<area>1</area>
<note>this is a 3rd note.</note>
</note>
Using XPath, the following code :
public class NotesExtractor {
public static List< String > getTextOf( Document doc, String tagName )
throws Exception
{
List< String > notes = new ArrayList<>();
XPathFactory xPathFactory = XPathFactory.newInstance();
XPath xPath = xPathFactory.newXPath();
NodeList xText =
(NodeList)xPath.evaluate(
"//" + tagName + "/text()", doc, XPathConstants.NODESET );
for( int i = 0; i < xText.getLength(); ++i ) {
Text textElt = (Text)xText.item( i );
String noteTxt = textElt.getTextContent().trim();
if( ! noteTxt.isEmpty())
{
notes.add( noteTxt.trim());
}
}
return notes;
}
public static void main( String[] args ) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setIgnoringElementContentWhitespace( true );
DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse( "Notes.xml" );
System.out.println( getTextOf( doc, "note" ));
}
outputs:
[Note 123123123, This is another note., this is a 3rd note.]
Related
XML:
<types>
<members>*</members>
<name>ApexClass</name>
</types>
<version>38.0</version>
I am trying to modify the xml as:
<types>
<members>test1</members>
<members>test1</members>
<members>test1</members>
<members>test1</members>
<name>ApexClass</name>
</types>
<version>38.0</version>
My current code looks like this:
public class Main {
static List<String> stringList = new ArrayList<String>();
public static void main(String[] args) {
try {
stringList.add("test1");
stringList.add("test2");
stringList.add("test3");
File fXmlFile = new File("C:\\Jenkins\\salesforce_ant_38.0\\sample\\mypkg\\package.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fXmlFile);
//optional, but recommended
//read this - http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName("types");
for (int temp = 0; temp < nList.getLength(); temp++) {
Node parentNode = nList.item(temp);
removeNodes(parentNode, doc);
createChildNodes(doc, parentNode, stringList);
}
// write the content into xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(fXmlFile.getPath()));
transformer.transform(source, result);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void removeNodes(Node parentNode, Document document) {
NodeList membersList = document.getElementsByTagName("members");
NodeList nameList = document.getElementsByTagName("name");
for (int i = 0; i <= membersList.getLength(); i++) {
Node memberNode = membersList.item(i);
if(memberNode != null) {
parentNode.removeChild(memberNode);
}
}
for (int i = 0; i <= nameList.getLength(); i++) {
Node nameNode = nameList.item(i);
if(nameNode != null) {
parentNode.removeChild(nameNode);
}
}
}
private static void createChildNodes(Document document, Node parentNode, List<String> stringList) {
Element version = null;
for (int i = 0; i < stringList.size(); i++) {
version = document.createElement("members");
version.setTextContent(stringList.get(i));
parentNode.appendChild(version);
}
version = document.createElement("name");
version.setTextContent("ApexClass");
parentNode.appendChild(version);
}
}
The output does not remove all the 'members' nodes, if the xml is like following:
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
</types>
<version>38.0</version>
</Package>
The output will be :
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>test1</members>
<members>test2</members>
<members>test3</members>
<name>ApexClass</name>
</types>
<version>38.0</version>
</Package>
which is correct, but if the xml is like above the output turns out to be:
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>test2</members>
<members>test1</members>
<members>test2</members>
<members>test3</members>
<name>ApexClass</name>
</types>
<version>38.0</version>
</Package>
Which is wrong, it should have deleted all the members node and then added the new members and name nodes.
Also it keeps adding space in between.
I want to get the File nodes of this xml document, can anyone help me with archive this issue?
I have this xml document:
<?xml version="1.0" encoding="UTF-8"?>
<Replies>
<FileList>
<File>cip13_test.rts</File>
<File>databar_lmt.rts</File>
<File>Test3.rts</File>
<File>databar2_lmt.rts</File>
<File>databar5_lmt.rts</File>
</FileList>
</Replies>
and I need to get all File-items from this.
I have this code but I get only cip13_test.rtx.
public static String GetFileList(String fileresponse) {
String xml = fileresponse;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = null;
InputSource is = new InputSource();
String textToShow = "";
StringBuilder resultsofList = new StringBuilder();
try {
db = dbf.newDocumentBuilder();
is.setCharacterStream(new StringReader(xml));
try {
Document doc = db.parse(is);
NodeList replies = doc.getElementsByTagName("Replies");
for (int i = 0; i < replies.getLength(); i++) {
Element element = (Element) replies.item(i);
NodeList inkstatus = element.getElementsByTagName("FileList");
for (int i2 = 0; i2 < inkstatus.getLength(); i2++) {
Element element2 = (Element) inkstatus.item(i2);
NodeList inklevel = element2.getElementsByTagName("File");
for (int i4 = 0; i4 < inklevel.getLength(); i4++) {
Element element4 = (Element) inklevel.item(i4);
Element line = (Element) inklevel.item(0);
if (line == null) {
inklevel = element4.getElementsByTagName("File");
line = (Element) inklevel.item(0);
}
textToShow = getCharacterDataFromElement(line);
resultsofList.append(textToShow+",");
}
}
}
} catch (SAXException e) {
// handle SAXException
} catch (IOException e) {
// handle IOException
}
} catch (ParserConfigurationException e1) {
// handle ParserConfigurationException
}
return String.valueOf(resultsofList);
}
This line is wrong:
Element line = (Element) inklevel.item(0);
It should be
Element line = (Element) inklevel.item(i4);
class HtmlTagmodifier {
public String htmlFileWriter(String cfile, String Listname, String Nodename, String nodevalue) {
try {
File fhtmlFile = new File(cfile);
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(fhtmlFile);
doc.getDocumentElement().normalize();
NodeList nList = doc.getElementsByTagName(Listname);
for (int temp = 0; temp < nList.getLength(); temp++) {
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE) {
Element eElement = (Element) nNode;
eElement.getElementsByTagName(Nodename).item(0).setTextContent(nodevalue);
}
}
Source source = new DOMSource(doc);
Result htmlresult = new StreamResult(fhtmlFile);
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform(source, htmlresult);
result2 = "Success";
} catch (Exception e) {
e.printStackTrace();
log.error("Error in html file writing " + e.toString());
JOptionPane.showMessageDialog(null, "Error in html file writing " + e.toString());
result2 = "Failed";
}
return result2;
}
public static void main(String[] args) {
HtmlTagmodifier.htmlfilewriter("test.html", "details", "customername", "customernamexxxxxx");
}
}
Output:
when i use this method to modify the tag values of html,tag name is changed successfully but meta data tag is added again in the html
please give me suggestion.
I have an XML file and I need to delete a specific node. The node to be deleted will be defined dynamically based on the logic. I have been searching in internet for a solution but couldn't delete my node still. am getting error - NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist
Below is a sample XML File. I need to delete the node <NameValuePairs> which has <name>Local Variables</name>. Below is my sample XML Files Java Code
Sample XML File
<?xml version="1.0" encoding="UTF-8"?>
<DeploymentDescriptors xmlns="http://www.tibco.com/xmlns/dd">
<name>Test</name>
<version>1</version>
<DeploymentDescriptorFactory>
<name>RepoInstance</name>
</DeploymentDescriptorFactory>
<DeploymentDescriptorFactory>
<name>NameValuePairs</name>
</DeploymentDescriptorFactory>
<NameValuePairs>
<name>Global Variables</name>
<NameValuePair>
<name>Connections1</name>
<value>7222</value>
<requiresConfiguration>true</requiresConfiguration>
</NameValuePair>
<NameValuePair>
<name>Connections2</name>
<value>7222</value>
<requiresConfiguration>true</requiresConfiguration>
</NameValuePair>
</NameValuePairs>
<NameValuePairs>
<name>Local Variables</name>
<NameValuePair>
<name>Connections3</name>
<value>8222</value>
<requiresConfiguration>true</requiresConfiguration>
</NameValuePair>
<NameValuePair>
<name>Connections3</name>
<value>8222</value>
<requiresConfiguration>true</requiresConfiguration>
</NameValuePair>
</NameValuePairs>
</DeploymentDescriptors>
Java Code
File fDestFile = new File("myfile.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document oDoc3 = dBuilder.parse(fDestFile);
NodeList oDestFlowList = oDoc3.getElementsByTagName("NameValuePairs");
for (int m = 0; m < oDestFlowList.getLength(); m++) {
NodeList oDestchildList = oDestFlowList.item(m).getChildNodes();
for (int n = 0; n < oDestchildList.getLength(); n++) {
Node oDestchildNode = oDestchildList.item(n);
if ("name".equals(oDestchildNode.getNodeName())) {
//oDestchildNode.getParentNode().removeChild(oDestchildNode); //Not Working
//oDoc3.getDocumentElement().removeChild(oDestchildNode); //Not Working
}
}
}
}
You need create a separate reference from the parent node as an Element so that you aren't referencing the node that you are removing:
File fDestFile = new File("src/myfile.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = null;
try {
dBuilder = dbFactory.newDocumentBuilder();
Document oDoc3 = null;
oDoc3 = dBuilder.parse(fDestFile);
NodeList oDestFlowList = oDoc3.getElementsByTagName("NameValuePairs");
// Loop through all 'NameValuePairs'
for (int m = oDestFlowList.getLength()-1; m >=0 ; m--) {
NodeList oDestchildList = oDestFlowList.item(m).getChildNodes();
// Loop through children of 'NameValuePairs'
for (int n = oDestchildList.getLength()-1; n >=0 ; n--) {
// Remove children if they are of the type 'name'
if(oDestchildList.item(n).getNodeName().equals("name")){
oDestFlowList.item(m).removeChild(oDestchildList.item(n));
// For debugging
System.out.println(oDestchildList.item(n).getNodeName());
}
}
}
Source source = new DOMSource(oDoc3);
Result result = new StreamResult(fDestFile);
Transformer transformer = null;
transformer = TransformerFactory.newInstance().newTransformer();
// Transform your XML document (i.e. save changes to file)
transformer.transform(source, result);
} catch (Exception e) {
// Catch the exception here
e.printStackTrace();
}
}
If you are still having issues, then I would think that it is an issue with the node types. This was working for me before I put the check in for 'oDestchildNode.getNodeType()' but I would look at what type of node you are returning and go from there.
Here is the final piece of code that finally worked
public static void main(String[] args) {
File fXmlSubFile = new File("Sub.xml");
File fXmlOriginalFile = new File("Original.xml");
File fDestFile = new File("myfile.xml");
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder;
FileChannel source = null;
FileChannel destination = null;
XPath xPath = XPathFactory.newInstance().newXPath();
try{
if (!fDestFile.exists()) {
fDestFile.createNewFile();
}
source = new FileInputStream(fXmlOriginalFile).getChannel();
destination = new FileOutputStream(fDestFile).getChannel();
if (destination != null && source != null) {
destination.transferFrom(source, 0, source.size());
}
if (source != null) {
source.close();
}
if (destination != null) {
destination.close();
}
dBuilder = dbFactory.newDocumentBuilder();
Document oSubDoc = dBuilder.parse(fXmlSubFile);
Document oDestDoc = dBuilder.parse(fDestFile);
oSubDoc.getDocumentElement().normalize();
oDestDoc.getDocumentElement().normalize();
String sDestExpression = "/DeploymentDescriptors/NameValuePairs";
String sSubExpression = "/NameValuePairs";
NodeList nodeDestList = (NodeList) xPath.compile(sDestExpression).evaluate(oDestDoc, XPathConstants.NODESET);
NodeList nodeSubList = (NodeList) xPath.compile(sSubExpression).evaluate(oSubDoc, XPathConstants.NODESET);
for (int i = nodeDestList.getLength()-1; i >=0 ; i--) {
Node oDestNode = nodeDestList.item(i);
if (oDestNode.getNodeType() == Node.ELEMENT_NODE) {
Element oDestElement = (Element) oDestNode;
for (int j =0; j<nodeSubList.getLength(); j++) {
Node oSubNode = nodeSubList.item(j);
if (oSubNode.getNodeType() == Node.ELEMENT_NODE) {
Element oSubElement = (Element) oSubNode;
if(oDestElement.getElementsByTagName("name").item(0).getTextContent().equals(oSubElement.getElementsByTagName("name").item(0).getTextContent())){
oDestNode.getParentNode().removeChild(oDestNode);
}
}
}
}
}
Source src = new DOMSource(oDestDoc);
Result result = new StreamResult(fDestFile);
Transformer transformer = null;
transformer = TransformerFactory.newInstance().newTransformer();
// Transform your XML document (i.e. save changes to file)
transformer.transform(src, result);
}catch(Exception ex){
System.out.println("error:"+ex.getMessage());
ex.printStackTrace();
}
}
I have an XML:
<?xml version="1.0" encoding="UTF-8"?>
<songs>
<song>
<title>Gracious</title>
<artist>Ben Howard</artist>
<genre>Singer/Songwriter</genre>
</song>
<song>
<title>Only Love</title>
<artist>Ben Howard</artist>
<genre>Singer/Songwriter</genre>
</song>
<song>
<title>Bad Blood</title>
<artist>Bastille</artist>
<genre>N/A</genre>
</song>
<song>
<title>Keep Your Head Up</title>
<artist>Ben Howard</artist>
<genre>Singer/Songwriter</genre>
</song>
<song>
<title>Intro</title>
<artist>Alt-J</artist>
<genre>Alternative</genre>
</song>
</songs>
and my Java code is:
public static void deleteSong(Song song) {
String songTitle = song.getTitle();
String songArtist = song.getArtist();
String songGenre = song.getGenre();
try {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
File file = new File("songs.xml");
Document doc = db.parse(file);
NodeList songList = doc.getElementsByTagName("song");
if (songList != null && songList.getLength() > 0) {
for (int i = 0; i < songList.getLength(); i++) {
Node node = songList.item(i);
Element e = (Element) node;
NodeList nodeList = e.getElementsByTagName("title");
String title = nodeList.item(0).getChildNodes().item(0)
.getNodeValue();
nodeList = e.getElementsByTagName("artist");
String artist = nodeList.item(0).getChildNodes().item(0)
.getNodeValue();
nodeList = e.getElementsByTagName("genre");
String genre = nodeList.item(0).getChildNodes().item(0)
.getNodeValue();
System.out.println(title + " Title");
System.out.println(songTitle + " SongTitle");
if (title.equals(songTitle)) {
if (artist.equals(songArtist)) {
if (genre.equals(songGenre)) {
doc.getFirstChild().removeChild(node);
}
}
}
}
}
MainDisplay.main(null);
} catch (Exception e) {
System.out.println(e);
}
}
The song to be deleted is passed into the method and then compared to the songs in the xml file. However, if the song matches a song in the xml, it isn't deleted? No exceptions come up.
You need to remove relevant node, in you code you are removing node of firstchild which seems to be incorrect.
And write back your changes to the file.
if (title.equals(songTitle) && artist.equals(songArtist) && genre.equals(songGenre) ) {
node.getParentNode().removeChild(node);
}
// write back to xml file
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(new File(filepath));
transformer.transform(source, result);
From what I see, you are only reading the documents. At some point, you will have to flush the changes back to the XML file.