How to read xml comment when using XDocument?
XDocument doc = XDocument.Load("joker.xml");
foreach (XElement element in doc.Descendants("server"))
{
//I use this to read server tag...
}
<?xml version="1.0" encoding="ISO-8859-1"?>
<ho>
<!-- For X use only -->
<servers>
<server NAME="xx" ></server>
<!-- Dummy servers -->
<server NAME="xx" ></server>
<server NAME="xx" ></server>
</servers>
</ho>
The Node object is the primary data type for the entire DOM.
A node can be an element node, an attribute node, a text node, or any other of the node types explained in the "Node types" chapter.
An XML element is everything from (including) the element's start tag to (including) the element's end tag.
XDocument xdoc = XDocument.Load("");
foreach (var node in xdoc.Descendants("servers").Nodes())
{
if (node is XComment)
{
//THEN READ YOUR COMMENT
}
}
Check node type when reading xml. If it's XComment then you are reading comment. E.g. in your case previous node of server element will be comment:
foreach(var s in doc.Descendants("server"))
{
var comment = s.PreviousNode as XComment;
if (comment != null)
Console.WriteLine(comment.Value); // outputs "Dummy servers"
}
you will have to use the XmlReader.Create method and read it and switch between the nodes to indicate which node it is current reading
Dont be fooled by the Create method... it reads the xml file in question but creates an instance of the XmlReader object:
http://msdn.microsoft.com/en-us/library/system.xml.xmlreader.create(v=vs.110).aspx
XmlReader xmlRdr = XmlReader.Create("Joker.XML");
// Parse the file
while (xmlRdr.Read())
{
switch (xmlRdr.NodeType)
{
case XmlNodeType.Element:
// Current node is an Xml Element
break;
case XmlNodeType.Comment:
// This is a comment so do something with xmlRdr.value
... and so on
PART 2 - for those who want to use LINQ (not that it makes a difference really)...
XDocument xml = XDocument.Load("joker.xml");
var commentNodes = from n in xml.Descendants("server")
where n.NodeType == XmlNodeType.Comment
select n;
foreach(XNode node in commentNodes)
{
// now you are iterating over the comments it has found
}
Related
I am trying to read a file produced by another developer. The file looks something like this. I am trying to read in the value for 'ProfileName', but when I look at the object in memory, I see null for the Value (capital V) attribute. The only place I can see the string "GolfLeague-Dual" is in the outerxml attribute, but I would have to parse through a bunch of just to get it.
<?xml version="1.0"?>
<TopNode>
<ProfileSettings>
<ProfileName value="GolfLeague-Dual" />
</ProfileSettings>
</TopNode>
Here is my code to try to read this:
XmlDocument doc = new XmlDocument();
doc.Load(directory + #"\Settings.xml");
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("//ProfileSettings");
foreach (XmlNode node in nodes) {
Console.WriteLine(node["ProfileName"].Value);
}
Your code is trying to get the inner value of the node, not an attribute called value. Try this instead...
foreach (XmlNode node in nodes) {
Console.WriteLine(node["ProfileName"].Attributes["value"].Value);
}
Here's a working dotnetfiddle...
https://dotnetfiddle.net/pmJKbX
I want to read all the nodes in the xml. Reading the top node without the loop goes fine, but I want to read all the nodes to get all the different temperatures for each city. This is the xml:
<servers>
<server name ="Stockholm">
<!-- data from Google weather -->
<name>Stockholm (Google)</name><!--Läser denna rad för tillfället-->
<url>http://www.yr.no/place/sweden/stockholm/stockholm/forecast.xml</url>
<xpath>/weatherdata/forecast/tabular/time/temperature</xpath>
</server>
<server name ="Göteborg">
<name>Göteborg (Google)</name> <url>http://www.yr.no/place/Sweden/V%C3%A4stra_G%C3%B6taland/Gothenburg/forecast.xml</url>
<xpath>/weatherdata/forecast/tabular/time/temperature</xpath>
</server>
<server name =" Malmö">
<name>Malmö (Google)</name>
<url>http://www.yr.no/place/sweden/scania/malmö/forecast.xml</url>
<xpath>/weatherdata/forecast/tabular/time/temperature</xpath>
</server>
</servers>
My code so far:
XmlDocument serverDoc = new XmlDocument();
serverDoc.Load("ServerUrls.xml");
XmlNodeList xml =
serverDoc.SelectNodes("servers/server");
foreach (var node in xml)
{
}
I know its not much. But cant seem to find information I can use properly. Been to MSDN and tried to figure it out from there, but to no result.
Thankful for all the help I can get.
As mentioned in the comment, you need to get URL of the XML where the actual temperature resides, as well as the corresponding XPath to locate the temperatures within the XML. Load XML from the URL into XmlDocument and then execute the XPath to extract the actual temperature values :
foreach (XmlNode node in xml)
{
// get information needed to extract temprature i.e XML location, and the XPath :
var loc = node.SelectSingleNode("url").InnerText;
var xpath = node.SelectSingleNode("xpath").InnerText;
// get temperature information
var doc = new XmlDocument();
doc.Load(loc);
var temperatures = doc.SelectNodes(xpath);
// iterate through temperatures and take action accordingly, f.e print the temperature
foreach(XmlNode temperature in temperatures)
{
Console.WriteLine(temperature.Attributes["value"].Value);
}
}
Here is xml that I want to read
<servers>
<server name=" PIOU PIOU || OPTIMAL" ca="1" continent_code="EU"
country="France" country_code="FR" ip="s1.mymumble.fr"
port="20129" region="" url="http://www.mymumble.fr" />
</servers>
Now when I read it I successfully get the elemnt 'servers' and I can read its innerxml as well i.e the correct node is created. but when I create a node with element 'server' the node is empty.
I guess the reason is the short form of starting and ending element used in the 'server' node.
But my problem is that the xml comes from some remote server and I cannot modify it, so I have to read it the way it is written.
Here is my code to read XML:
List<XmlNode> nodeList = new List<XmlNode>();
XmlDocument doc = new XmlDocument();
while (reader.Read())
{
//keep reading until we see my element
if (reader.Name.Equals("server") && (reader.NodeType == XmlNodeType.Element))
{
XmlNode myNode = doc.ReadNode(reader);
Debug.Log(reader.IsEmptyElement ? "its empty" : "not empty");
//this always prints "its empty"
nodeList.Add(myNode);
}
}
foreach( XmlNode node in nodeList)
{
Debug.Log("child:\t"+node.FirstChild.InnerXml);
}
See the documentation for IsEmptyElement. In particular, this example:
<item num="123"/> (IsEmptyElement is true).
<item num="123"></item> (IsEmptyElement is false, although element content is empty).
Your node is considered empty because it uses the short form. There is no element "content," but there are attributes.
Have you checked the node that you created (i.e. myNode) to see that it contains the attributes?
XmlReader is kind of low level for your needs...
Wouldn't it be easier to parse your XML with Linq2Xml?
var xmlStr = #"<servers>
<server name="" PIOU PIOU || OPTIMAL"" ca=""1"" continent_code=""EU""
country=""France"" country_code=""FR"" ip=""s1.mymumble.fr""
port=""20129"" region="""" url=""http://www.mymumble.fr"" />
</servers>";
var doc = XDocument.Parse(xmlStr);
var servers = doc.Root.Elements("server")
.Select(e => new{
name = (string)e.Attribute("name"),
ca = (int)e.Attribute("ca"),
country = (string)e.Attribute("country")
//etc...
});
XmlDocument has method called "GetNodes", that will help you.
Good Evening All, and happy weekend!.
I have been trying all day to understand how to parse my simple XML file so I can understand it enough to write a personal project I want to work on.
I have been reading articles on this site and others but cannot get past where I am :(
My XML Document is ...
<XML>
<User>
<ID>123456789</ID>
<Device>My PC</Device>
</User>
<History>
<CreationTime>27 June 2013</CreationTime>
<UpdatedTime>29 June 2013</UpdatedTime>
<LastUsage>30 June 2013</LastUsage>
<UsageCount>103</UsageCount>
</History>
<Configuration>
<Name>Test Item</Name>
<Details>READ ME</Details>
<Enabled>true</Enabled>
</Configuration>
</XML>
I am trying to get the value in the details element (READ ME). Below is my code
// Start Logging Progress
Console.WriteLine("Test Application - XML Parsing and Creating");
Console.ReadKey();
// Load XML Document
XmlDocument MyDoc = new XmlDocument(); MyDoc.Load(#"E:\MyXML.XML");
// Select Node
XmlNode MyNode = MyDoc.SelectSingleNode("XML/Configuration/Details");
// Output Node Value
Console.WriteLine(String.Concat("Details: ", MyNode.Value));
// Pause
Console.ReadKey();
My console application is running and outputing "Target: " but not giving me the detail within the element.
Can somebody see why this is happening, and perhaps give me advice if I am completely off the wheel? I have no previous knowledge in reading XML files; hence where I am now :)
Thanks! Tom
With the your XPATH expression
// Select Node
XmlNode MyNode = MyDoc.SelectSingleNode("XML/Configuration/Details");
your are selection an element so the type of the MyNode will be XmlElement but the Value of an XmlElement is always null (see on MSDN) so you need to use XmlElement.InnerText or XmlElement.InnerXml isntead.
So the changed your code to
// Output Node Value
Console.WriteLine(String.Concat("Details: ", MyNode.InnerText));
Or you can select the content of an element with using the XPATH text() function, in this case MyNode will be XmlText where you get its value with Value:
// Select Node
XmlNode MyNode = MyDoc.SelectSingleNode("XML/Configuration/Details/text()");
// Output Node Value
Console.WriteLine(String.Concat("Details: ", MyNode.Value));
As a sidenote if you are anyway learning XML manipulation in C# you should check out LINQ to XML which is another/newer way to working with XML in C#.
Just for interest, a little-known "simple" syntax is this:
XmlDocument myDoc = new XmlDocument();
myDoc.Load(#"D:\MyXML.XML");
string details = myDoc["XML"]["Configuration"]["Details"].InnerText;
Note that this (and the XPath approach) could go pop if your XML doesn't conform to the structure you're expecting, so you'd ideally put some validation in there as well.
U can use Xpath library for that (u must include "System.Xml.XPath"):
XmlDocument document = new XmlDocument();
document.Load("MyXml.xml");
XPathNavigator navigator = document.CreateNavigator();
foreach (XPathNavigator nav in navigator.Select("//Details"))
{
Console.WriteLine(nav.Value);
}
the above code iterate over every node called (Details) extracting information and print it.
If you want to retrieve a particular value from an XML file
XmlDocument _LocalInfo_Xml = new XmlDocument();
_LocalInfo_Xml.Load(fileName);
XmlElement _XmlElement;
_XmlElement = _LocalInfo_Xml.GetElementsByTagName("UserId")[0] as XmlElement;
string Value = _XmlElement.InnerText;
Value contains the text value
Here is my XML :
<?xml version="1.0" encoding="utf-8" ?>
<Selection>
<ID>1</ID>
<Nom>Name 1</Nom>
<DateReference>0</DateReference>
<PrefixeMedia>Department</PrefixeMedia>
<FormatExport>1630</FormatExport>
<TraceAuto>Oui</TraceAuto>
<SubID></SubID>
</Selection>
<Selection>
<ID>2</ID>
<Nom>Name 1</Nom>
<DateReference>0</DateReference>
<PrefixeMedia>Department</PrefixeMedia>
<FormatExport>1630</FormatExport>
<TraceAuto>1</TraceAuto>
<SubID>1</SubID>
</Selection>
My problem is I would like to modify for example the node content of <Nom>Name 1</Nom> which is located in <Selection></Selection> which have <ID>1</ID> (Search by ID)
I'm using XElement and XDocument to do simple search but I need some help to solve this problem above. (Developpment on SilverLight
Best Regards.
Another way to do this is using XmlDocument:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"\path\to\file.xml");
// Select the <nom> node under the <Selection> node which has <ID> of '1'
XmlNode name = xmlDoc.SelectSingleNode("/Selection[ID='1']/Nom");
// Modify the value of the node
name.InnerText = "New Name 1";
// Save the XML document
xmlDoc.Save(#"\path\to\file.xml");
If you don't know how to get at the correct <Nom> node to update, the trick is to first select a <Selection> node that contains the correct <ID> node, then you can get that <Nom> node.
Something like:
XElement tree = <your XML>;
XElement selection = tree.Descendants("Selection")
.Where(n => n.Descendants("ID").First().Value == "1") // search for <ID>1</ID>
.FirstOrDefault();
if (selection != null)
{
XElement nom = selection.Descendants("Nom").First();
nom.Value = "Name one";
}
Note 1: By using Descendants("ID").First() I expect every Selection node to contain an ID node.
Note 2: And every Selection node contains a Nom node
Note 3: Now you still have to store the whole XML, if that's what you need.