C# Parsing/Saving XML Documents - c#

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.

Related

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...

Grab All XML Elements of a Specific Type: Even nested elements

I am parsing an XML document in C# ASP.NET. Is there a way/function that I don't know of to get all the elements of the tag "course"?
The format of the XML is like so:
<a>
<g1>
<course></course>
<g9>
<course></course>
... more course elements
</g9>
<course></course>
<g2>
<g3>
<course></course>
...
</g3>
</g2>
</g1>
</a>
When I do the following code I get back no "course" elements, is there a simple function that can grab all these elements in one go?
XmlDocument xdoc = new XmlDocument();
xdoc.Load("http://kjkjkj.com");
XmlNodeList list = xdoc.DocumentElement.SelectNodes("course");
// if I debug: list.count = 0 but if I look at xdoc.DocumentElement.outerXml
// its the correct XML so I did parse the file & get XML contents.
// Is there any C# equivalent of document.getElementsByTagName("course"); ???
You were close:
XmlNodeList list = xdoc.DocumentElement.SelectNodes("//course");
Prefixing with // will grab all the nodes in the document named course, no matter where they are.
As an alternative you should consider parsing your XML with Linq to Xml which integrates nicely with Linq to objects. The equivalent syntax for the same there is
var courses = xdoc.Descendants("course");

Append xml document to bottom of existing xml doc

I have an xml document and want to append another xml at the bottom of it. Using the xml classes in .NET, what is the quickest way to do this (in 3.5)?
Thanks
Quickest as in most efficient, or quickest as in simplest? For example:
XDocument doc1 = XDocument.Load(...);
XDocument doc2 = XDocument.Load(...);
// Copy the root element of doc2 to the end of doc1
doc1.Root.Add(doc2.Root);
doc1.Save(...);
Alternatively, you may want:
// Copy the *contents* of the root element of doc2 to the end of doc1
doc1.Root.Add(doc2.Root.Descendants());
If you can be more precise about your requirements, we may be able to help more. Note that an XML document can only have one root element, so you can't just put one document after another.
I doubt that you will be able to do this using the XML classes. XML libraries typically aim to protect you from creating poorly-formed XML, and the concatenation of two XML documents will be poorly formed because the document node will have two child elements.
If the .Net libraries do allow you to do this, I suggest you raise it as a bug.
var xml = new XmlDocument();
xml.AppendChild(...);
xml.PrependChild(...);
If you really want to add a second root node the fastest way would be to read the first file line by line and add it to the second file. That's a very dirty way and you'll get an invalid xml file!
System.IO.StreamWriter file1 = System.IO.File.AppendText(path);
System.IO.StreamReader file2 = new System.IO.StreamReader(path2)
while(!file2.EndOfStream)
{
file1.WriteLine(file2.ReadLine());
}
file1.Close();
file2.Close();
I even don't like this solution!

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. :)

C# Use Linq to Extract a single XML attribute for each XML file in a directory

How do I use Linq to extract a single XML attribute form each XML file in a directory and put that element in a C# list. Do I have to loop thru each file one-by-one? The XML files are quite large so I'd like to do this without loading the entire file into memory.
Thanks,
j
Unless the files are massive (100 MB+) I would be unable to turn down the elegance of this code:
var result = Directory.GetFiles(filePath)
.Select(path => XDocument.Load(path))
.Select(doc => doc.Root.Element("A").Attribute("B").Value)
.ToList();
I really hope your XML files are not that big though...
You do have to go through every file, and this will mean at least parsing enough of the XML content of each file to get to the required attribute.
XDocument (i.e. LINQ to SQL) will parse and load the complete document in each case, so you might be better using an XmlReader instance directly. This will require more work: you will have to read the XML nodes until you get to the right one, keeping track of where you are.

Categories