I have an XML file looks like this:
<?xml version="1.0" encoding="utf-8" ?>
<PathMasks>
<Mask desc="Masks_X1">
<config id="01" mask="88" />
<config id="03" mask="80" />
<config id="51" mask="85" />
</Mask>
<Mask desc="Masks_X2">
<config id="70" mask="1" />
<config id="73" mask="6" />
</Mask>
<Types>
<path id="01" desc="TC->PP1" />
<path id="02" desc="TC->PP2" />
<path id="03" desc="TC->PPn" />
</Types>
</PathMasks>
How to parse the file and get all the data of Mask_X1 as following:
id value
=====
01, 88
03, 80
51, 85
The .NET framework I am using is 2.0
As you're working with .Net 2.0 you won't have Linq and will therefore need to use XPath, this sample should help you out.
XmlDocument doc = new XmlDocument();
doc.Load(pathToXmlDoc);
XmlNode node = doc.SelectSingleNode("/PathMasks/Mask[#desc='Masks_X1']");
foreach (XmlNode config in node)
{
Console.WriteLine("{0}\t{1}",
config.Attributes["id"].Value,
config.Attributes["mask"].Value);
}
Using XmlDocument (slower, larger memory footprint, read/write, works the same way XML DOMs everywhere work):
XmlDocument d = new XmlDocument();
d.Load(filename);
string xpath = "/PathMasks/Mask[#desc='Mask_X1']/config"
foreach (XmlElement elm in d.SelectNodes(xpath))
{
Console.WriteLine(elm.GetAttribute("id"), elm.GetAttribute("desc"));
}
Using XPathDocument (faster, smaller memory footprint, read-only, weird API):
XPathDocument d = new XPathDocument(filename);
string xpath = "/PathMasks/Mask[#desc='Mask_X1']/config"
XPathNodeIterator iter = d.CreateNavigator().Select(xpath);
while (iter.MoveNext())
{
Console.WriteLine(iter.Current.GetAttribute("id"), iter.Current.GetAttribute("desc'));
}
I'm sure there's a perfectly good reason why there isn't a method of XPathNavigator that returns an IEnumerable<XPathNavigator> so that you can iterate over the results of an XPath query like a normal person, but I haven't been able to work it out.
Using Linq to XML :
XDocument doc = XDocument.Load(filename);
var query = from mask in doc.Root.Elements("Mask")
where mask.Attribute("desc").Value == "Masks_X1"
from config in mask.Elements("config")
select new
{
id = config.Attribute("id").Value,
value = config.Attribute("mask").Value
};
foreach(var mask in query)
{
Console.WriteLine("{0}\t{1}", mask.id, mask.value);
}
Use XDocument and query into it with Linq to XML
XDocument doc = XDocument.Load("file.xml");
var linqtoxml = from node in document.Descendants("Mask")
where (string)node.Attribute("desc").Value == "Masks_X1"
select node;
foreach (var mask in linqtoxml)
{
// pull data out of here into a structure of your choosing
}
Related
I have Multiple XML Files that look like below
<?xml version="1.0" encoding="UTF-8"?>
<schema>
<sp_transaction_id name="sp_transaction_id" value="1" />
<sp_year name="sp_year" value="2015" />
<sp_first_name name="sp_first_name" value="James" />
<sp_gender name="sp_gender" value="Male" />
<sp_date_of_birth name="sp_date_of_birth" value="06-06-1999" />
</schema>
The XML Format i think is in Key-Value Pairs.
I want to extract these values and store it into a database(SQL Server 2012) table, with the name(eg; sp_year) as Column Name and value(eg; 2015) as the Column value using ASP.NET C#.
I think i can upload the file and read it like this :
string fileName = Path.GetFileName(FileUpload1.PostedFile.FileName);
string filePath = Server.MapPath("~/Uploads/") + fileName;
FileUpload1.SaveAs(filePath);
string xml = File.ReadAllText(filePath);
But thats pretty much it ( Sorry Im a beginner ). Please Guide me. Thanks
You can use the following code to get the key value pairs
XDocument doc = XDocument.Load(filePath);
var schemaElement = doc.Element("schema");
foreach (var xElement in schemaElement.Elements())
{
Console.WriteLine(xElement.Attribute("name").Value + ":" + xElement.Attribute("value").Value);
}
Elements method returns all elements inside schema element.
However I suggest changing xml file to this format, if possible
<?xml version="1.0" encoding="UTF-8"?>
<schema>
<KeyValuePair name="sp_transaction_id" value="1" />
<KeyValuePair name="sp_year" value="2015" />
<KeyValuePair name="sp_first_name" value="James" />
<KeyValuePair name="sp_gender" value="Male" />
<KeyValuePair name="sp_date_of_birth" value="06-06-1999" />
</schema>
For reading data from an xml file you don't need to upload it.You can give path of xml and read from it.You can use following method to read from xml
public static XmlDocument LoadXmlDocument(string xmlPath)
{
if ((xmlPath == "") || (xmlPath == null) || (!File.Exists(xmlPath)))
return null;
StreamReader strreader = new StreamReader(xmlPath);
string xmlInnerText = strreader.ReadToEnd();
strreader.Close();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlInnerText);
return xmlDoc;
}
For reading data from xml you can use
XmlDocument xmlDoc = LoadXmlDocument(xmlPath);
XmlNodeList nodes = xmlDoc .SelectNodes("//*");
foreach (XmlElement node in nodes)
{
.
.
.
}
In foreach loop you can get your required values e.g sp_year
The answer below shows how to create an XmlDocument from it.
I would suggest to use it as a User-Defined class if you know whether Xml schema change.
First of all you should create POCO class appropriate to Xml file schema using XmlAnnotations.
Secondly:
Having path of the file:
XmlSerializer serializer = new XmlSerializer(typeof(definedclass));
using (FileStream fs = File.Open(pathtofile))
using (XmlReader reader = XmlReader.Create(fs))
{
var xmlObject = serializer.Deserialize(reader);
}
xmlObject is now your user-defined class with values from xml.
Regards,
Rafal
You can load the files into an XDocument & then use Linq-To-XML to extract the required information. The example code below loads all name/value pairs into an array of class :
class MyXMLClass
{
public String FieldName { get; set; }
public String Value { get; set; }
}
The code gets all "schema" descendants (just one as it is the top level element), then selects all elements inside the & creates a new class object for each extracting the name & value.
XDocument xd = XDocument.Load("test.xml");
MyXMLClass[] xe =
xd.Descendants("schema")
.Elements()
.Select(n => new MyXMLClass {FieldName = n.Attribute("name").Value, Value = n.Attribute("value").Value})
.ToArray();
My XML looks like this:
<data>
<location ....>
<stores>
<store ....></store>
<store ... ></store>
</stores>
</location>
</data>
I want to loop through all the location elements, and then loop through all the stores.
I also want access to the attributes of both location and store elements.
I have loaded the xml document:
var doc = new XmlDocument();
doc.LoadXml(myXmlAsString);
Let's say this is your sample XML
<data>
<location sample="something">
<stores>
<store atrb="1">store1</store>
<store atrb="2">store2</store>
</stores>
</location>
<location>
<stores>....</stores>
</location>
</data>
Then using XDocument of System.Xml.Linq, you access all the locations, stores and their attributes like this
var xmlString = File.ReadAllText(#"C:\YourDirectory\YourFile.xml");
XDocument geneva = XDocument.Parse(xmlString);
var locations = geneva.Descendants("location");
foreach (var location in locations)
{
var sampleAttribute = location.Attribute("sample").Value;
var stores = location.Descendants("store");
foreach (var store in stores)
{
var value = store.Value;
var atrbValue = store.Attribute("atrb").Value;
}
}
If you dont want to use XmlSerializer to get the typed data you can get nodes by criteria with SelectSingleNode or SelectNodes methods. This will give you ability to iterate through location elemets.
I would suggest creating classes to deserialize to because its easier to work with.
Loop through locations:
XmlNodeList xnList = doc.SelectNodes("/data/location");
foreach(XmlNode node in xnList)
{
//your code goes here..
}
Loop through all stores:
XmlNodeList xnList = doc.SelectNodes("/data/location/stores");
foreach(XmlNode node in xnList)
{
//your code here..
}
I have the below XML as:
<Requests xmlResponse="true">
<Request response="yes" responsewait="120000" sequence="1" type="Fulfillment">
<RequestData>
<PrintControl>FTP</PrintControl>
<User>81DF</User>
<Documents>
<AddressChangeLetter>
<DocumentInfo>
<AddressChange AddressChangeId="109346" Branch="418" LastChangeDate="">
<Name>AAA NOVAK</Name>
<TaxID>123123121</TaxID>
<OldAddress1>BOX 216</OldAddress1>
<OldAddress2>NYANE 68017</OldAddress2>
<OldAddress3 />
<OldAddress4 />
<NewAddress1>P O BOX 216</NewAddress1>
<NewAddress2>CERESCO NE 68017</NewAddress2>
<NewAddress3 />
<NewAddress4 />
<DateChanged>05/08/2013</DateChanged>
<AccountInfo AcctNum="231232311" AcctStatusCodes="IX" />
</AddressChange>
</DocumentInfo>
</AddressChangeLetter>
</Documents>
</RequestData>
I wanted to get the name or the value which is under the tag "Documents". Since in the above XML, the tag under the "Document" tag is "AddressChangeLetter", therefore, I want to get this name. How will I do it.
Something along the lines of... (it's not perfect, but it'll get you started - Google the functions I've used to get it working properly):
XmlDocument xml = new XmlDocument();
xml.Load(yourPathGoesHere)
XmlNodeList addressNodes = xml.GetElementsByTagName("AddressChange");
foreach (XmlNode oneNode in addressNodes) {
myVariableToGrabNames = oneNode["Name"].InnerText;
}
This can be done pretty easily using Linq to XML e.g.
var xml = ...;
var xdoc = XDocument.Parse(xml);
foreach (var e in xdoc.Descendants("Documents").Elements())
{
var name = e.Name; // AddressChangeLetter
}
I have a XML file like below:
<report timestamp="3201" reportVersion="2" request="3981135340">
<question timedOut="false" time="3163" attempts="2" correct="true" id="13">
<answer status="attempt">
<radioButton correct="false" value="true" id="17" />
</answer>
<answer status="correct">
<radioButton correct="true" value="true" id="15" />
</answer>
</question>
</report>
I want to read the child nodes based on 'status' attribute of 'answer' node.
Use XmlReader (fastest but forward only), XDocument (LINQ to XML) or XmlDocument. See the examples in the msdn documentation.
Using LINQ to XML:
using System.Xml.Linq;
var doc = XDocument.Parse(xml); // or XDocument.Load()
var elements = from e in doc.Descendants("answer")
where e.Attribute("status").Value == "attempt"
select e;
// elements will be IEnumerable<XElement>
Use XmlDocument and XPath:
XmlDocument document = new XmlDocument();
//here you should load your xml for example with document.Load();
XmlNodeList nodes = document.SelectNodes("/report/question/answer[#status = 'correct']/radioButton");
Just modify the XPath to your needs.
try this one..
foreach (XmlNode xnode in xdoc.SelectNodes("report/question/answer"))
{
if (xnode.Attributes.GetNamedItem("status").Value == "correct")
{
string value = xdoc.SelectSingleNode("report/question/answer[#status='correct']/radioButton").Attributes.GetNamedItem("id").Value;
}
if (xnode.Attributes.GetNamedItem("status").Value == "attempt")
{
string value = xdoc.SelectSingleNode("report/question/answer[#status='attempt']/radioButton").Attributes.GetNamedItem("id").Value;
}
}
I need to load an XML document into my Dictionary<string,string> object.
XML looks like:
<nodes>
<node id="123">
<text>text goes here</text>
</node>
</nodes>
How can I do this using XmlDocument?
I want readability over performance, and I find XmlReader to be hard to read b/c you have to keep checking the node type.
Assuming ID is the key and the value of the <text> node is the value, you can use LINQ:
XDocument xDoc;
using(StringReader sr = new StringReader("thexml"))
{
xDoc = XDocument.Load(sr);
}
myDictionary = xDoc.Descendants("node").ToDictionary(x => x.Attribute("id").Value, x => x.Descendants("text").First().Value);
Well, there is a reason why XML parsing has improved since 2.0, but if you just want a sample that parses that fragment without using XmlReader, this should work. I'm sure there are other ways of doing this:
XmlDocument doc = new XmlDocument();
doc.LoadXml(#"<nodes><node id=""123""><text>text goes here</text></node><node id=""321""><text>more text goes here</text></node></nodes>");
foreach (XmlNode nodes in doc.GetElementsByTagName("nodes"))
{
foreach (XmlNode node in nodes.ChildNodes)
{
XmlNodeList list = node.SelectNodes("text");
if (list.Count > 0)
{
Console.Write("{0}='{1}'\n", node.Attributes["id"].Value, list[0].InnerText);
}
}
}
Console.WriteLine("Done.");
Console.ReadKey();