what i want to do is it appear all related data from selected xml file. i already declare the node path to be search which is XmlNodeList xnList = xml.SelectNodes("/Patient/Patient/Name");. However, my output only display the last data and not the overall data for path needed.
This is my xml file.
<Patient>
<Patient>
<LevelPriority>0</LevelPriority>
<Name>w</Name>
<Id>1</Id>
</Patient>
<Patient>
<LevelPriority>0</LevelPriority>
<Name>asf</Name>
<Id>2</Id>
</Patient>
<Patient>
<LevelPriority>0</LevelPriority>
<Name>add</Name>
<Id>3</Id>
</Patient>
and this is my output.
what i want it to appear is:
w
asf
add
rather than just the last data add.
this is my code in viewForm.
namespace SliceLink
{
public partial class ViewForm : Form
{
public Form3()
{
InitializeComponent();
XmlDocument xml = new XmlDocument();
xml.Load("C:\\Users\\HDAdmin\\Documents\\SliceEngine\\SliceEngine\\bin\\Debug\\saya.xml");
XmlNodeList xnList = xml.SelectNodes("/Patient/Patient/Name");
foreach (XmlNode xn in xnList)
{
string name = xn.InnerText;
textBox1.Text = name;
}
}
}
}
how to make it view the for all the data required?
You have to append the new text (name) to the text that is already there:
foreach (XmlNode xn in xnList)
{
string name = xn.InnerText;
textBox1.Text = textBox1.Text + name;
}
Also, you might want to insert some delimiter (here: a whitespace character):
foreach (XmlNode xn in xnList)
{
string name = xn.InnerText;
textBox1.Text = textBox1.Text + " " + name;
}
Check textBox1.Text.Length for zero if you don't want to insert the space before the first item.
Related
I have a simple function which will simply change and read the value.
void ParseXml(string XmlFile)
{
string totalval = "";
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(new StringReader(XmlFile));
string xmlPathPattern = "//name";
XmlNodeList mynodelist = xmldoc.SelectNodes(xmlPathPattern);
foreach (XmlNode node in mynodelist)
{
XmlNode name = node.FirstChild;
name.Value = "asd";//here I am trying to change value
totalval = totalval + "Name=" + name.OuterXml + "\n";
}
xmldoc.Save(XmlFile);
print(totalval);
}
This is my .xml file.
<name>John</name>
I can successfully read the value but it is not changing the value from .xml file.After running the program it must be like this
<name>asd</name> .
Where is my mistake ?
Obviously, the XMLFile is not a file path, it is xml string. So, you should define a valid path to save it.
xmldoc.Save("samplefile.xml");
or if you want to set the XmlFile variable with modified xml;
XmlFile = xmldoc.OuterXml;
Complete codes look like;
void ParseXml(string XmlFile)
{
string totalval = "";
XmlDocument xmldoc = new XmlDocument();
xmldoc.Load(new StringReader(XmlFile));
string xmlPathPattern = "//name";
XmlNodeList mynodelist = xmldoc.SelectNodes(xmlPathPattern);
foreach (XmlNode node in mynodelist)
{
XmlNode name = node.FirstChild;
name.Value = "asd";//here I am trying to change value
totalval = totalval + "Name=" + name.OuterXml + "\n";
}
//XmlFile = xmldoc.OuterXml;
xmldoc.Save("samplefile.xml");
print(totalval);
}
If I'm not wrong - you need to fire disposable to save stream. Easiest way - wrap with using
void ParseXml(string XmlFile)
{
string totalval = "";
using(XmlDocument xmldoc = new XmlDocument())
{
xmldoc.Load(new StringReader(XmlFile));
string xmlPathPattern = "//name";
XmlNodeList mynodelist = xmldoc.SelectNodes(xmlPathPattern);
foreach (XmlNode node in mynodelist)
{
XmlNode name = node.FirstChild;
name.Value = "asd";//here I am trying to change value
totalval = totalval + "Name=" + name.OuterXml + "\n";
}
xmldoc.Save(XmlFile);
print(totalval);
}
}
this is my xml document
<Names>
<Name1 type="M" name = "John">
</Name1>
</Names>
and I want to parse through the document so that I will get Name1,type,its value, name and its value
Use XmlDocument class and use its ChildNodes / Attributes property.
var xml = "<Names><Name type=\"M\" name=\"John\"></Name></Names>";
var doc = new XmlDocument();
doc.LoadXml(xml);
var nodes = doc.DocumentElement.ChildNodes;
foreach (XmlNode node in nodes)
{
Console.WriteLine(node.Name + " : " + node.Value);
foreach (XmlAttribute attr in node.Attributes)
{
Console.WriteLine(attr.Name + " : " + attr.Value);
}
}
You can explore further from here, like GetElementsByTagName method or recursively explore the child nodes..
string xml = #"
<parent>
<child>
<nested />
</child>
<child>
<other>
</other>
</child>
</parent>
";
XmlReader rdr = XmlReader.Create(new System.IO.StringReader(xml));
while (rdr.Read())
{
if (rdr.NodeType == XmlNodeType.Element)
{
Console.WriteLine(rdr.LocalName);
}
}
The result of the above will be
parent
child
nested
child
other
XmlDocument objXmldoc = new XmlDocument();
objXmldoc.Load(txtBrowseFilePath.Text);
XmlNodeList objxmlNodeList=null;
objxmlNodeList = objXmldoc.SelectNodes(#"/AppXmlLogWritter/LogData[LogDateTime/text()[starts-with(. , '" + dateTimePickerFromDate.Value.ToString("yyyyMMdd") + "')]]");
DataSet ds = new DataSet();
ds.ReadXml(objxmlNodeList);
How to convert XmlNodeList to Xmlstring to bind xml data with dataset
xml file
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<AppXmlLogWritter>
<LogData>
<LogID>5678201301161640382918</LogID>
<LogDateTime>20130116164037</LogDateTime>
<LogType>Message</LogType>
<LogFlag>RISLogFlag</LogFlag>
<LogApplication>BaburaoLogApplication</LogApplication>
<LogModule>RISLogModule</LogModule>
<LogLocation>RISLogLocation</LogLocation>
<LogText>BaburaoLogText</LogText>
</LogData>
<LogData>
<LogID>5678201301161640382919</LogID>
<LogDateTime>20130116164038</LogDateTime>
<LogType>Warning</LogType>
<LogFlag>MACLogFlag</LogFlag>
<LogApplication>MACLogApplication</LogApplication>
<LogModule>MACLogModule</LogModule>
<LogLocation>MACLogLocation</LogLocation>
<LogText>MACLogText</LogText>
</LogData>
</AppXmlLogWritter>
try such a function:
private string XmlNodeListToString(XmlNodeList nodeList)
{
String returnStr = "";
if (nodeList != null)
{
foreach (XmlNode node in nodeList)
{
returnStr += node.OuterXml;
}
}
/*
//I think this is not needed from Dataset.ReadXml
returnStr = returnStr .Replace("&", "&");
returnStr = returnStr.Replace("<", "<");
returnStr = returnStr.Replace(">", ">");
returnStr = returnStr.Replace("'", "'");
returnStr = returnStr.Replace("\"", """);
*/
return "<Root>"+returnStr+"</Root>";
}
Also from your comments seems that you have a long file name issue.
try objXmldoc.Load(#txtBrowseFilePath.Text);
or if it does not succeed
try something else like preceding filepath with \\?\ as i found out in this link
For example, "\\?\D:\very long path".
Thank you very much for reading my question.
and this is my xml file. (for node Songs, many childNodes named Song)
<?xml version="1.0" encoding="utf-8" ?>
<xmlData>
<version>1.0</version>
<Songs>
<Song>
<artist>mic</artist>
<track>2</track>
<column>happy</column>
<date>14</date>
</Song>
<Song>
<artist>cool</artist>
<track>2</track>
<column>work</column>
<date>4</date>
</Song>
</Songs>
</xmlData>
reading xml, i use the following code:
XmlDocument doc = new XmlDocument();
doc.Load(xmlFilePath);
XmlNode versionNode = doc.SelectSingleNode(#"/xmlData/version");
Console.WriteLine(versionNode.Name + ":\t" + versionNode.InnerText);
XmlNode SongsNode = doc.SelectSingleNode(#"/xmlData/Songs");
Console.WriteLine(SongsNode.Name + "\n");
XmlDocument docSub = new XmlDocument();
docSub.LoadXml(SongsNode.OuterXml);
XmlNodeList SongList = docSub.SelectNodes(#"/Songs/Song");
if (SongList != null)
{
foreach (XmlNode SongNode in SongList)
{
XmlNode artistDetail = SongNode.SelectSingleNode("artist");
Console.WriteLine(artistDetail.Name + "\t: " + artistDetail.InnerText);
XmlNode trackDetail = SongNode.SelectSingleNode("track");
Console.WriteLine(trackDetail.Name + "\t: " + trackDetail.InnerText);
XmlNode columnDetail = SongNode.SelectSingleNode("column");
Console.WriteLine(columnDetail.Name + "\t: " + columnDetail.InnerText);
XmlNode dateDetail = SongNode.SelectSingleNode("date");
Console.WriteLine(dateDetail.Name + "\t: " + dateDetail.InnerText + "\n");
}
}
it seems working.
but how can i write the change to xml file?
maybe, i will change some childNode in Song, and may delete the whole chindNode by artist keyword.
is it possible such as this function
bool DeleteSongByArtist(string sArtist);
bool ChangeNodeInSong(string sArtist, string sNodeName, string value);
because the "Reading solution is "XmlDucoment", so it is better if "changing solution" by using "XmlDocument"
but, if you have better idea to read and change the xml file, please give me the sample code... and please don't write a name of solution such as "Ling to xml"...acutally, i do many testes, but failed.
Welcome to Stackoverflow!
You can change the nodes simply by setting a new .Value or in your case .InnerText.
Sample
// change the node
trackDetail.InnerText = "NewValue"
// save the document
doc.Save(xmlFilePath);
More Information
How To: Modify an Existing Xml File
MSDN - XmlDocument.Save Method
You need to use an XmlWriter. The easiest way to do it would be something like this...
using(XmlWriter writer = new XmlWriter(textWriter))
{
doc.WriteTo(writer);
}
Where textWriter is your initialized Text Writer.
Actually, forget that... the easiest way is to call...
doc.Save(xmlFilePath);
To delete an artist by artist name add the following method:
bool DeleteSongByArtist(XmlDocument doc, string artistName)
{
XmlNodeList SongList = doc.SelectNodes(#"/Songs/Song");
if (SongList != null)
{
for (int i = SongList.Count - 1; i >= 0; i--)
{
if (SongList[i]["artist"].InnerText == artistName && SongList[i].ParentNode != null)
{
SongList[i].ParentNode.RemoveChild(SongList[i]);
}
}
}
}
You probably want to clean it up a bit more to be more resilient. When you call it, change your initial code to be like this. Don't create the subDocument as you want to work with the entire XmlDocument.
XmlDocument doc = new XmlDocument();
doc.Load(xmlFilePath);
XmlNode versionNode = doc.SelectSingleNode(#"/xmlData/version");
Console.WriteLine(versionNode.Name + ":\t" + versionNode.InnerText);
XmlNode SongsNode = doc.SelectSingleNode(#"/xmlData/Songs");
Console.WriteLine(SongsNode.Name + "\n");
XmlNodeList SongList = doc.SelectNodes(#"/Songs/Song");
if (SongList != null)
{
foreach (XmlNode SongNode in SongList)
{
XmlNode artistDetail = SongNode.SelectSingleNode("artist");
Console.WriteLine(artistDetail.Name + "\t: " + artistDetail.InnerText);
XmlNode trackDetail = SongNode.SelectSingleNode("track");
Console.WriteLine(trackDetail.Name + "\t: " + trackDetail.InnerText);
XmlNode columnDetail = SongNode.SelectSingleNode("column");
Console.WriteLine(columnDetail.Name + "\t: " + columnDetail.InnerText);
XmlNode dateDetail = SongNode.SelectSingleNode("date");
Console.WriteLine(dateDetail.Name + "\t: " + dateDetail.InnerText + "\n");
}
}
You aren't able to save your changes because you made changes to an entirely new document!
You likely meant to do the following:
XmlNode SongsNode = doc.SelectSingleNode(#"/xmlData/Songs");
Console.WriteLine(SongsNode.Name + "\n");
// Don't make a new XmlDocument here! Use your existing one
XmlNodeList SongList = SongsNode.SelectNodes(#"/Song");
At this point SongList is still living inside doc. Now when you call:
doc.Save(xmlFilePath);
Your changes will be saved as you intended.
If you're looking to delete nodes that match certain criteria:
// Use XPath to find the matching node
XmlNode song = SongsNode.SelectSingleNode(#"/Song[artist='" + artist + "']");
// Remove it from its Parent
SongsNode.RemoveChild(song);
If you're looking to add a new node:
// Create the new nodes using doc
XmlNode newSong = doc.CreateElement("Song");
XmlNode artist = doc.CreateElement("artist");
artist.InnerText = "Hello";
// Begin the painstaking process of creation/appending
newSong.AppendChild(artist);
// rinse...repeat...
// Finally add the new song to the SongsNode
SongsNode.AppendChild(newSong);
You could do
XmlNodeList SongList = doc.SelectNodes(#"//Songs/Song");
The // tells it to select the Songs node anywhere in document. This is better than
doc.SelectNodes(#"/document/level1/music/Songs")
Note that the above statement is oviously not for your xml, but to prove a point about //
Using // removes the need for your docSub document and SongsNode element.
To add then delete a song, just use the following
XmlDocument doc = new XmlDocument();
XmlElement ea = doc.SelectSingleNode("//songs");
XmlElement el = doc.CreateElement("song");
XmlElement er;
ea.AppendChild(el);
//doing my work with ea
//you could use innerxml.
el.InnerXml = "<artist>Judas Priest</artist><track>7</track><column>good</column><date>1</date>";
//or you can treat each node as above
er = doc.CreateElement("Name");
el.AppendChild(er);
er.InnerText = "The Ripper";
//but you don't nead this song any more?
ea.RemoveChild(el);
//so it's gone.
And thats all there is to it.
please don't write a name of solution such as "Ling to xml"...acutally, i do many testes, but failed.
Still I think, this is a very good time to start to use Linq2Xml. If you don't like it, just ignore.
XDocument xDoc = XDocument.Load(new StringReader(xml));
//Load Songs
var songs = xDoc.Descendants("Song")
.Select(s => new
{
Artist = s.Element("artist").Value,
Track = s.Element("track").Value,
Column = s.Element("column").Value,
Date = s.Element("date").Value,
})
.ToArray();
//Delete Songs
string songByArtist="mic";
xDoc.Descendants("Song")
.Where(s => s.Element("artist").Value == songByArtist)
.Remove();
string newXml = xDoc.ToString();
xml:
<?xml version="1.0" encoding="utf-8" ?>
<StudentList>
<student>
<name>Ram</name>
<Id>1</Id>
</student>
<student>
<name>Hari</name>
<Id>2</Id>
</student>
<student>
<name>Gita</name>
<Id>3</Id>
</student>
<student>
<name>Sita</name>
<Id>4</Id>
</student>
</StudentList>
In page load:
XmlDocument XD = new XmlDocument();
XD.Load(System.Web.HttpContext.Current.Server.MapPath("XmlFile.xml"));
XmlNodeList nodeListName = XD.GetElementsByTagName("student");
foreach (XmlNode xNode in nodeListName)
{
foreach (XmlElement xelement in xNode)
{
PlaceHolder pshd = new PlaceHolder();
LblDisplay.Text += xelement.FirstChild.Value + " ";
string Name += xelement.FirstChild.Value;
}
LblDisplay.Text += "<br/>";
}
i want to catch only name from the above xml file but i get name and id both.How can i do it plz help.
XmlDocument xml = new XmlDocument();
xml.LoadXml(System.Web.HttpContext.Current.Server.MapPath("XmlFile.xml"));
XmlNodeList xnList = xml.SelectNodes("/StudentList/student");
foreach (XmlNode xn in xnList)
{
string name= xn["name"].InnerText;
string Id= xn["Id"].InnerText;
}
Instead of iterating over xNode you just want its FirstChild:
foreach (XmlNode xNode in nodeListName)
{
string name = xNode.FirstChild.InnerText;
LblDisplay.Text += name + "<br/>";
}
You can also use LINQ to XML (in the System.Xml.Linq namespace), using XDocument:
XDocument xDoc = XDocument.Load(System.Web.HttpContext.Current.Server.MapPath("XmlFile.xml"));
var names = from x in xDoc.Descendants("student")
select x.Element("name");
foreach (XElement studentName in names)
{
LblDisplay.Text += studentName.Value + " ";
}
LblDisplay.Text += "<br />";
If you want the id instead, you can substitute "Id" in the select x.Element("name"); line.
Alternatively, you could grab both name and Id and return them as a collection of anonymous types:
var students = from x in xDoc.Descendants("student")
select new
{
name = x.Element("name").Value,
id = x.Element("Id").Value
};
Which you could then access thusly:
foreach (var student in students)
{
LblDisplay.Text += student.name + " student.Id + " ";
}
Or whatever you wanted to do with it.
You can use XPath all the way:
nodeList = XD.SelectNodes("//student/name")
foreach (XMlNode node in nodeList){
LblDisplay.Text += node.Value + "<br/>";
}
String fileName = #"C:\Documents and Settings\aritra.ghosh\Desktop\Student.xml";
XmlDocument xDoc = new XmlDocument();
xDoc.Load(fileName);
XmlNodeList list = xDoc.SelectNodes("StudentList/student/name");
foreach (XmlNode item in list)
{
Console.WriteLine(item.InnerText);
}