Why doesn't XDocument.Parse() parse my XML properly? - c#

I am trying to use XDocument.Parse(string s) to parse some XML that is being returned from a REST based API. After the XML is parsed, it creates a new XDocument, but the document doesn't contain the properly parsed XML nodes. The name of the first node is the correct node name, but the value is the the concatenation of all the text from the XML, regardless of which Element is belongs to. Can anybody help me figure out what is going on?
XML
<sci_reply version="1.0">
<send_message>
<device id="00000000-00000000-00000000-00000000">
<error id="303">
<desc>Invalid target. Device not found.</desc>
</error>
</device>
<error>Invalid SCI request. No valid targets found.</error>
</send_message>
</sci_reply>
Debug View of XDocument Object

That's the expected behavior. The Value of a an XML element is concatenation of values of all its children. If you want to actually access the XML, read something about LINQ to XML or classes in the System.Xml.Linq namespace.

Thats just the debugger being nice.
The root is being displayed with all of its children.

Related

How to find nodes in XML File using Line number C#?

I have below XML files. While I'm using it in Process its gives me error like
[2016-06-22 19:29:53 IST] ERROR: "Line 15 column 20: character content of element "electronics" invalid; must be equal to "foods", "goods" or "mobiles" at XPath
/products/product[1]/item_type"
This XPath /products/product[1] is not correct. it's returns by their system.
So, I have to search it and replace with original value through Line No only.
Order.xml
<products>
<product>
<country>AE</country>
<sale>false</sale>
<item_type>foods</item_type>
</product>
<product>
<country>IN</country>
<sale>false</sale>
<item_type>goods</item_type>
</product>
<product>
<country>US</country>
<sale>false</sale>
<item_type>electronics</item_type>
</product>
<product>
<country>AM</country>
<sale>false</sale>
<item_type>mobiles</item_type>
</product>
</products>
Please let me know to do search using Line No(15) in XML document
You should not rely on line/colmns numbers when dealing with xml. Xml does not care much for whitespace and formatting is a merely convenience for readabilty; Although it is correctly reported in your example, I would not trust it will alway be that way in future. Interstingly the xpath is also incorrect but lets not dwell on that for the moment.
You need to take back control of the problem... You should create your own validating reader and capture the validation error while the xml is being parsed. How you do this will depend on which framework your using. Either XmlValidatingReader or, XmlReader with the appropriate XmlReaderSettings.
You can set up a callback/eventhandler to capture the error as the xml file is being read, so you can be certain your in the correct place and have all the information you need to handle the error to hand. Using an XmlReader will also allow you to continue to process the entire file and not just stop at the first error.
The code is too big for SO and we'd require a lot more information from you to do it but a google search will find lots of examples including this one from microsoft: https://msdn.microsoft.com/en-us/library/w5aahf2a(v=vs.100).aspx
Construct a new XmlReaderSettings instance.
Add an XML schema to the Schemas property of the XmlReaderSettings instance.
Specify Schema as the ValidationType.
Specify ValidationFlags and a ValidationEventHandler to handle schema validation errors and warnings encountered during validation.
Pass the XmlReaderSettings object to the Create method of the XmlReader class along with the XML document, creating a schema-validating XmlReader.
Call Read() to run through the xml from start to end.
Would this work for you?
string[] lines = File.ReadAllLines(#"C:\order.xml", Encoding.UTF8);
var line15 = lines[14];
XmlDocument doc = new XmlDocument();
doc.Load(#"C:\order.xml");
XmlElement el =(XmlElement)doc.SelectSingleNode("/products/product[1]/item_type");
if(el != null) { el.ParentNode.RemoveChild(el); }
you can remove node by using above code...using proper Xpath you can remove all the item_type which is not equals to foods,good or mobiles.
Try this,
var xml = XDocument.Load(#"C:\order.xml", LoadOptions.SetLineInfo);
var lineNumbers = xml.Descendants()
.Where(x => !x.Descendants().Any() && //exact node contains the value
x.Value.Contains("foods"))
.Cast<IXmlLineInfo>()
.Select(x => x.LineNumber);
int getLineNumber = lineNumbers.First();

C# Parsing/Saving XML Documents

My tasks seems to sound simple but is proving very difficult. I have a XML file like below:
<?xml version="1.0" encoding="UTF-8"?>
<ref:ReferralDocument xmlns:ref="http://ref.com" xmlns:gen="http://ref.com"
xmlns:h="http://www.w3.org/1999/xhtml" xmlns:pbr="ref.com"
xmlns:xsi="ref.com" schemaVersion="2.9">
<ref:MessageDetails>
<gen:TestID>
<gen:IdValue>2412665651</gen:IdValue>
<gen:IdScheme>Test</gen:IdScheme>
<gen:IdType>Person</gen:IdType>
</gen:TestID>
</ref:MessageDetails>
<gen:Name>
<gen:StructuredName>
<gen:GivenName>Test</gen:GivenName>
<gen:FamilyName>Test</gen:FamilyName>
</gen:StructuredName>
<gen:NameType>Current Name</gen:NameType>
</gen:Name>
</ref:MessageDataRef>
I want to read every XML element in to a XML Element object. As store them in a List or Array of XML Elements.
//Create new document
var document = new XmlDocument();
document.Load("C:\\Users\\liam.mccann\\Documents\\test.xml");
After loading in in I haven't had any success in getting every element only seem to be able to get the first.
So simple Load XML Document >> Validate XML >> Get Scheme Version from first Element >> Parse To XML Element List.
After parsing i hope it would be easy to restructure the document and save it again. And the document been the same.
Hopefully someone is able to help!
I want to read every XML element in to a XML Element object. As store
them in a List or Array of XML Elements.
You could do the following:
var array = document.SelectNodes("/descendant-or-self::*")
.OfType<XmlElement>()
.ToArray();
Having said that, if all you're intending is:
After parsing i hope it would be easy to restructure the document and
save it again.
then storing the elements in an array is probably not the optimal approach. You can use the XmlDocument class itself (or better yet - the new LINQ approach: System.Xml.Linq.XDocument).
Here's the MSDN document that hopefully can get you started: http://msdn.microsoft.com/en-us/library/bb387084%28v=vs.110%29.aspx.

Using XSD.exe for c# code gen, ignores empty nodes in XML?

Maybe I'm not doing this correctly. But I'm using MusicXML, along with XSD.exe to generate the C# classes against the DTD.
According to the documentation, along with a sample xml file, the <NOTE> element contains an empty <CHORD> element, if the <NOTE> is a part of a <CHORD>. The code generated looks like this:
[System.Xml.Serialization.XmlElementAttribute("chord", typeof(empty))]
When I deserialize the XML into a c# object, it works great, but the <CHORD> seems to disappear. Does .NET just ignore the CHORD element in this sample XML?
<note>
<chord/>
<pitch>
<step>E</step>
<alter>-1</alter>
<octave>4</octave>
</pitch>
<duration>1</duration>
</note>
Thanks!
Do you mean the chord element dissapears when you serialize to XML, as null elements don't serialize by default
If you want to render it as an empty element like
<chord />
you can set use the isnullable property
XML Serialization and null value - C#
As linked in another question you might want to have a look at this article about the representation of null in XML Schema files:
http://www.ibm.com/developerworks/xml/library/ws-tip-null/index.html

Reading oddly-formatted XML file C#

I need some help with reading an oddly-formatted XML file. Because of the way the nodes and attributes are structured, I keep running into XMLException errors (at least, that's what the output window is telling me; my breakpoints refuse to fire so that I can check it). Anyway, here's the XML. Anyone experienced anything like this before?
<ApplicationMonitoring>
<MonitoredApps>
<Application>
<function1 listenPort="5000"/>
</Application>
<Application>
<function2 listenPort="6000"/>
</Application>
</MonitoredApps>
<MIBs>
<site1 location="test.mib"/>
</MIBs>
<Community value="public"/>
<proxyAgent listenPort="161" timeOut="2"/>
</ApplicationMonitoring>
Cheers
EDIT: Current version of the parsing code (file path shortened - Im not actually using this one):
XmlDocument xml = new XmlDocument();
xml.LoadXml(#"..\..\..\ApplicationMonitoring.xml");
string port = xml.DocumentElement["proxyAgent"].InnerText;
Your problem in loading the XML is that xml.LoadXml expects you to pass the xml document as a string, not a file reference.
Try instead using:
xml.Load(#"..\..\..\ApplicationMonitoring.xml");
Essentially in your original code you are telling it that your xml document is
..\..\..\ApplicationMonitoring.xml
And I'm sure you can now see why there is a parse exception. :) I've tested this with your xml document and the modified load and it works fine (except for the issue that Only Bolivian Here pointed out with the fact that your inner Text is not going to return anything.
For completeness you probably want:
XmlDocument xml = new XmlDocument();
xml.Load(#"..\..\..\ApplicationMonitoring.xml");
string port = xml.DocumentElement["proxyAgent"].Attributes["listenPort"].Value;
//And to get stuff more specifically in the tree something like this
string function1 = xml.SelectSingleNode("//function1").Attributes["listenPort"].Value;
Note the use of the Value property on the attribute and not the ToString method which won't do what you are expecting.
Exactly how you extract the data from the xml is probably dependant on what you are doing with it. For example you may want to get a list of Application nodes to enumerate over with a foreach by doing this xml.SelectNodes("//Application").
If you are having trouble with extdacting stuff though that is probably the scope of a different question since this was just about how to get the XML document loaded.
xml.DocumentElement["proxyAgent"].InnerText;
The proxyAgent element is self closing. InnerText will return the string inside of an XML element, in this case, there is no inner elements.
You need to access an attribute of the element, not the InnerText.
Try this:
string port = xml.GetElementsByTagName("ProxyAgent")[0].Attributes["listenPort"].ToString();
Or use Linq to XML:
http://msdn.microsoft.com/en-us/library/bb387098.aspx
And... your XML is not malformed...

Parsing a file containing xml elements in C#

I have a big xml file which is composed of multiple xml files. The file structure is like this.
<xml1>
</xml1>
<xml2>
</xml2>
<xml3>
</xml3>
.
.
<xmln>
</xmln>
I want to process each XML file by a LINQ statement but I am not sure how to extract each XML element individually from the file and continue the iteration until the end. I figured experts here would be able to give me the nudge I am looking for. My requirement is to extract the individual elements so i could load into a XDoc element for further processing and continue on through the subsequent elements. Any help on this would be greatly appreciated.
Thanks for reading!!
Assuming each element is a valid XML, you can wrap your document in a top-level tag and then load it just fine:
<wrap>
<xml1>
</xml1>
<xml2>
</xml2>
</wrap>
You can use the System.Xml reference, which includes a lot of built-in functionality, and it allows you to declare an XmlTextReader. More info here.
If this is an error log with individual well formed xml elements, you probably don't want to load it as an XMLDocument. A better option is to use an XPathDocument created with an XmlReader where the XmlReaderSettings specify ConformanceLevel.Fragment. Then you can use an XPathNavigator to access your elements and attributes as needed. See the third answer in this forum post for sample code.
...late by just a year and then some. :)

Categories