Very simple XML reading in C#.NET - c#

I want to read the following XML file:
Words.xml:
<?xml version="1.0" encoding="utf-8" ?>
<words>
<word>Bat</word>
<word>Dog</word>
<word>Car</word>
</words>
..using XDocument. I keep getting a "Non white space characters cannot be added to content" error with this code:
XDocument doc = new XDocument("words.xml");
foreach (XElement element in doc.Descendants("word"))
{
Console.WriteLine(element.Value);
}

You need to load the document like this:
XDocument doc = XDocument.Load("words.xml");
The reason your original code fails is you are using XDocument (Object[]) constructor that normally expects list of XElement objects like:
var doc = new XDocument(new XElement("Root"));

Related

Document.SelectNodes returning zero nodes. Is there anything wrong in my xml?

I have following xml. But, when I am loading it and selecting node I am getting 0 nodes. Is there anything wrong with my xml?
Code to load xml :
XmlDocument doc = new XmlDocument();
doc.LoadXml(strOfferListing);
XmlNamespaceManager mgr = new XmlNamespaceManager(doc.NameTable);
mgr.AddNamespace("ns", "http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd");
mgr.AddNamespace("root", "http://mws.amazonservices.com/schema/Products/2011-10-01");
var nodes = doc.SelectNodes("//GetMatchingProductResponse");
This is my xml file :
<?xml version="1.0" encoding="UTF-8"?>
<GetMatchingProductResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01"><GetMatchingProductResult ASIN="0470265957" status="Success"><Product><Identifiers><MarketplaceASIN><MarketplaceId>XXXXXXXXXX</MarketplaceId><ASIN>0470265957</ASIN></MarketplaceASIN></Identifiers><AttributeSets><ns2:ItemAttributes xml:lang="en-US" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd"><ns2:Author>Milton H. Erickson</ns2:Author><ns2:Author>Ernest L. Rossi</ns2:Author><ns2:Binding>Hardcover</ns2:Binding><ns2:Edition>1st</ns2:Edition><ns2:IsEligibleForTradeIn>true</ns2:IsEligibleForTradeIn><ns2:Label>Irvington Publishers</ns2:Label><ns2:Languages><ns2:Language><ns2:Name>english</ns2:Name><ns2:Type>Published</ns2:Type></ns2:Language><ns2:Language><ns2:Name>english</ns2:Name><ns2:Type>Original Language</ns2:Type></ns2:Language><ns2:Language><ns2:Name>english</ns2:Name><ns2:Type>Unknown</ns2:Type></ns2:Language></ns2:Languages><ns2:ListPrice><ns2:Amount>211.86</ns2:Amount><ns2:CurrencyCode>USD</ns2:CurrencyCode></ns2:ListPrice><ns2:Manufacturer>Irvington Publishers</ns2:Manufacturer><ns2:NumberOfItems>1</ns2:NumberOfItems><ns2:NumberOfPages>512</ns2:NumberOfPages><ns2:PackageDimensions><ns2:Height Units="inches">1.70</ns2:Height><ns2:Length Units="inches">9.40</ns2:Length><ns2:Width Units="inches">6.30</ns2:Width><ns2:Weight Units="pounds">1.85</ns2:Weight></ns2:PackageDimensions><ns2:ProductGroup>Book</ns2:ProductGroup><ns2:ProductTypeName>ABIS_BOOK</ns2:ProductTypeName><ns2:PublicationDate>1979-10-01</ns2:PublicationDate><ns2:Publisher>Irvington Publishers</ns2:Publisher><ns2:SmallImage><ns2:URL>http://ecx.images-amazon.com/images/I/51geup2R-DL._SL75_.jpg</ns2:URL><ns2:Height Units="pixels">75</ns2:Height><ns2:Width Units="pixels">56</ns2:Width></ns2:SmallImage><ns2:Studio>Irvington Publishers</ns2:Studio><ns2:Title>Hypnotherapy: An Exploratory Casebook</ns2:Title></ns2:ItemAttributes></AttributeSets><Relationships /><SalesRankings><SalesRank><ProductCategoryId>book_display_on_website</ProductCategoryId><Rank>562887</Rank></SalesRank><SalesRank><ProductCategoryId>3558816011</ProductCategoryId><Rank>63</Rank></SalesRank><SalesRank><ProductCategoryId>173514</ProductCategoryId><Rank>38091</Rank></SalesRank></SalesRankings></Product></GetMatchingProductResult></GetMatchingProductResponse>

Append New Element in XML VB or C#

I apologize if this question is too easy for you as I am just starting to learn how XML works. What I am trying to do is to append a new element to App/Library and for example I started with this.
<?xml version="1.0" encoding="utf-8"?>
<App>
<Library>
<Count>100</Count>
<Track>
<TrackID>1</TrackID>
<Name>New York</Name>
<Artist>Snow Patrol</Name>
</Track>
</Library>
</App>
what I am trying to do is to add another track to my existing XML.
<Track>
<TrackID>2</TrackID>
<Name>Chasing Cars</Name>
<Artist>Snow Patrol</Name>
</Track>
There are a couple of ways to deal with xml manipulation in .NET. The older style using System.Xml.XmlDocument or using System.Xml.Linq.XDocument approach.
Here is an example on how to do it using XmlDocument:
var xml = "Baz";
var doc = new XmlDocument();
doc.LoadXml(xml); //Load up the original xml string into XmlDocument object
var fooNode = doc.SelectSingleNode("//foo"); //use xpath to get to the top level foo element
var newBar = doc.CreateElement("bar"); //Create a new bar element and assign it's inner text
newBar.InnerText = "Baz2";
fooNode.AppendChild(newBar); //append the newly created bar element to foo
and here is an example on how to do it using XDocument (which is much more simpler):
var xml = "<?xml version=\"1.0\" encoding=\"utf-8\"?><foo><bar>Baz</bar></foo>";
var xdoc = XDocument.Parse(xml); //Load up the original xml string into Linq XDocument object
xdoc.Root.Add(new XElement("bar", "Bar2")); //Add <bar>Bar2</bar> to foo (which is root of the document)
Here is a running example:
https://dotnetfiddle.net/vY7Vag

Using XmlTextReader to Loop though XML attributes that have the same name

I am doing some practice code with the XmlTextReader. I have written some very basic XML as shown here:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<task name="mixed_sprite_task_test">
<sprite>
<type>animatedSprite</type>
<id>0</id>
<name>animatedSprite</name>
<fileName>iyezoz</fileName>
<startingPositionX>200</startingPositionX>
<startingPositionY>200</startingPositionY>
<sheetSizeX>12</sheetSizeX>
<sheetSizeY>35</sheetSizeY>
<startingFrameX>0</startingFrameX>
<startingFrameY>0</startingFrameY>
<startingState>standing</startingState>
<movementSpeed>15</movementSpeed>
<frameDelay>0.055</frameDelay>
</sprite>
<sprite>
<type>staticSprite</type>
<id>0</id>
<name>staticSprite</name>
<fileName>Super_Mario_63</fileName>
<startingPositionX>0</startingPositionX>
<startingPositionY>0</startingPositionY>
</sprite>
<sprite>
<type>simpleSprite</type>
<id>0</id>
<name>simpleSprite</name>
<fileName>imgres</fileName>
<startingPositionX>100</startingPositionX>
<startingPositionY>100</startingPositionY>
<movementSpeed>15</movementSpeed>
</sprite>
</task>
This file shows that I have a task. In the task I have 3 sprites.
In my code I want to loop through each sprite and collect the information.
I can get the data from the first sprite with no issue. Is there a certain way to loop through an xml with attributes of the same name?
Thank-you!
I prefer Linq2Xml.
var xDoc = XDocument.Parse(xmlstring); //or XDocument.Load(filename);
var sprites = xDoc.Descendants("sprite")
.Select(s=>s.Elements()
.ToDictionary(e=>e.Name.LocalName,e=>(string)e))
.ToList();
You can use it as
var type = sprites[0]["type"];
or can take a safe action
string delay;
if (sprites[1].TryGetValue("frameDelay", out delay))
{
Console.WriteLine(delay);
}
You can select all the nodes named "sprite"
var myXml = new XmlDocument();
myXml.Load(myDocument);
XmlNode rootElement = myXml.DocumentElement;
foreach (XmlNode item in rootElement.SelectNodes(#"/task/sprite"))
{
// do stuff with node
}

Issue in removing all the nodes from XML file using LINQ

I am trying to remove all the nodes from the XML file. But it's removing the root node open tag also .Using C# anf Linq
Input:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!--Log the error count and error message-->
<root>
<ErrData>
<Count>1</Count>
<Timestamp>2011-11-21T11:57:12.3539044-05:00</Timestamp>
</ErrData>
<ErrData>max of 20 ErrData elements</ErrData>
</root>
Expected OP:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!--Log the error count and error message-->
<root>
</root>
Actual OP:EDITED
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!--Log the error count and error message-->
<root />
Code :
XDocument docs = XDocument.Load(path);
try
{
docs.Descendants("ErrData").Remove();
}
CODE:
Below is the code i am using ,the concept is the error count and timestamp are logged into XML file.Once its reached the threshold value,email will be send by function and remove all the nodes from the xml. Then when the next error comes it will start entering in to the xml file as below,
XDocument doc = null;
XElement el;
if (!System.IO.File.Exists(path))
{
doc = new XDocument(new XDeclaration("1.0", "utf-8", "no"));
el = new XElement("root");
//el = new XElement("root");
XComment comment = new XComment("Log the error count and error message");
doc.Add(comment);
}
else
{
doc = XDocument.Load(path);
}
XElement p1 = new XElement("ErrData");
XElement p1Count = new XElement("Count", eventCount);
XElement p1Windowsatrt = new XElement("Timestamp", windowStart);
p1.Add(p1Count );
p1.Add(p1Windowsatrt );
if (doc.Root != null)
{
el = doc.Root;
el.Add(p1);
}
else
{
el = new XElement("root");
el.Add(p1);
}
try
{
doc.Add(el);//Line throwing the exeception
}
catch (Exception e)
{
}
finally
{
doc.Save(path);
}
Use docs.Root.Nodes().Remove().
<root /> is valid XML for a tag with no content (self-closing tags). If you absolutely need an opening and closing tag you need to put some content in the root node like a comment or text.
The confusion is in your very first sentence: "I am trying to remove all the nodes/elements from the XML file." Which one is it? Do you want to remove all nodes, or all elements?
There are five types of nodes in XML: elements, text, comments, processing instructions, and attributes. If you use "node" and "element" interchangeably, as you are here, you're going to have no end of trouble working with XML.
What you got, <root/>, is the correct output for code that removes all descendant nodes: it's a single element named root with no content.
What you expect,
<root>
</root>
is a single element named root that contains a child text node containing whitespace, probably a newline. The code you wrote removes all descendant nodes, not just descendant element nodes, and so it removed this text node as well.

c# Parsing XML issue

I am using this code to try and read this XML below, but it is not read anything in the foreach loop and skipping that. Thanks.
C#
XElement _xml;
_xml = XElement.Parse(PostResult);
foreach (XElement value in _xml.Elements("ServiceDelivery")
.Element("StopMonitoringDelivery")
.Elements("MonitoredStopVisit"))
{
StopFeed _item = new StopFeed();
_item.A= value.Element("PublishedLineName").Value;
_item.B = value.Element("DirectionName").Value;
listBox1.Items.Add(_item);
}
XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Siri version="1.0" xmlns="http://www.siri.org.uk/">
<ServiceDelivery>
<ResponseTimestamp>2011-10-04T11:45:36.415+01:00</ResponseTimestamp>
<ResponseMessageIdentifier>1d8bc237-2df6-43e6-af56-c750d3089eb6</ResponseMessageIdentifier>
<StopMonitoringDelivery version="1.0">
<ResponseTimestamp>2011-10-04T11:45:36.415+01:00</ResponseTimestamp>
<RequestMessageRef>1</RequestMessageRef>
<MonitoredStopVisit>
<RecordedAtTime>2011-10-04T11:45:36.412+01:00</RecordedAtTime>
<MonitoringRef>020035057</MonitoringRef>
<MonitoredVehicleJourney>
<FramedVehicleJourneyRef>
<DataFrameRef>-</DataFrameRef>
<DatedVehicleJourneyRef>-</DatedVehicleJourneyRef>
</FramedVehicleJourneyRef>
<VehicleMode>bus</VehicleMode>
<PublishedLineName>28</PublishedLineName>
<DirectionName>blahblah</DirectionName>
<OperatorRef>153</OperatorRef>
<MonitoredCall>
<AimedDepartureTime>2011-10- 04T11:48:00.000+01:00</AimedDepartureTime>
</MonitoredCall>
</MonitoredVehicleJourney>
</MonitoredStopVisit>
</StopMonitoringDelivery>
</ServiceDelivery>
</Siri>
I think you forgot the namespace. Have a look at XNamespace
XNamespace xn= "http://www.siri.org.uk/";
foreach (XElement value in _xml.Elements(xn+ "ServiceDelivery")
.Element(xn+ "StopMonitoringDelivery")
.Elements(xn+ "MonitoredStopVisit"))
{
....
}
The root element is Siri.
Either use:
XElement value in _xml.Root.Elements("ServiceDelivery")
.Element("StopMonitoringDelivery")
.Elements("MonitoredStopVisit"))
or
XElement value in _xml.Element("Siri")
.Elements("ServiceDelivery")
.Element("StopMonitoringDelivery")
.Elements("MonitoredStopVisit"))
/B
try _xml.Elements("//ServiceDelivery") or _xml.Elements("Siri/ServiceDelivery"), you forgot that your ServiceDelivery node is child of Siri node.
Or maybe the XML namespace is the problem, check this page and see how XmlNamespaceManager can be used.

Categories