Reading child nodes of xml file [duplicate] - c#

This question already has answers here:
Reading value of an XML node
(3 answers)
Closed 8 years ago.
I have created an Xml file with example contents as follows:
<?xml version="1.0" encoding="utf-8"?>
<W-TIBCPTRs>
<W-TIBCPTR>
<TYPTRT>FDR2 R</TYPTRT>
<CLAFCNO VALIDE="NON">5b1</CLAFCNO>
<NUMCLI>0067781</NUMCLI>
<TYPACT>D</TYPACT>
</W-TIBCPTR>
<W-TIBCPTR>
<TYPTRT>FDR2 R</TYPTRT>
<CLAFCNO>511</CLAFCNO>
<NUMCLI>0068078</NUMCLI>
<TYPACT>D</TYPACT>
</W-TIBCPTR>
</W-TIBCPTRs>
i try this
XmlNodeList rowElements = doc.SelectNodes("W-TIBCPTRs/W-TIBCPTR");
foreach (XmlElement rowElement in rowElements)
{
foreach (XmlElement valueElement in rowElement.ChildNodes)
{
strin[] k=valueElement.Name;
}
}
I need to selectNodes automaticly because I can have a xml file with different nodes
Stock childNodes in array, I need these values (TYPTRT,CLAFCNO,NUMCLI,TYPACT)

It's easy to do with Linq to Xml (I suggest to use it instead old XmlDocument API):
var xdoc = XDocument.Load(path_to_xml);
var result = from t in xdoc.Root.Elements("W-TIBCPTR")
select new {
TYPTRT = (string)t.Element("TYPTRT"),
CLAFCNO = (string)t.Element("CLAFCNO"),
NUMCLI = (string)t.Element("NUMCLI"),
TYPACT = (string)t.Element("TYPACT")
};
Result:
[
{
TYPTRT: "FDR2 R",
CLAFCNO: "5b1",
NUMCLI: "0067781",
TYPACT: "D"
},
{
TYPTRT: "FDR2 R",
CLAFCNO: "511",
NUMCLI: "0068078",
TYPACT: "D"
}
]
NOTE: Currently you are selecting element's name. If you want to get inner text of all sub-elements in array, you can use:
string[] items = rowElement.ChildNodes.OfType<XmlElement>()
.Select(e => e.InnerText)
.ToArray();
That will return array of four strings for each W-TIBCPTR element in your sample xml. Same with Linq to Xml will look like:
var result = from t in xdoc.Root.Elements("W-TIBCPTR")
select t.Elements().Select(e => e.Value).ToArray();

Use Linq to XML
var doc= XDocument.Load(<path>);
var values = from c in doc.Descendants("W-TIBCPTR")
select new
{
TYPTRT = c.Element("TYPTRT").Value,
CLAFCNO = c.Element("CLAFCNO").Value
NUMCLI = c.Element("NUMCLI").Value
TYPACT = c.Element("TYPACT").Value
});

Related

How to seperate strings from a serialized XML node

I have an serialized XML file. This shows the relevant part:
I am reading this XML file with this (code snippet):
temp = Path.GetFileNameWithoutExtension(s);
var document = new XmlDocument();
document.Load(s);
var root = document.DocumentElement;
var node = root["ScenarioDescription"];
var text = node?.InnerText;
var ArmyNode = root["ArmyFiles"];
var ArmyText = ArmyNode?.InnerText;
However, ArmyText returns the concatenation of all three strings that make up the ArmyFiles node. I need them as three separate strings. How can I do this?
This code works to read all the strings in the node and place them into a list:
foreach (XmlElement A in ArmyNode)
{
var ArmyTemp = A.InnerText;
ArmyList.Add(ArmyTemp);
}
var ArmyText = ArmyNode?.InnerText;

Need to select Data from XML file C#

What I'm trying to do is get data from my XML file which has been merged with two others and selected each venue from that file and try to add the value to a list so I can manipulate it further.
This is one of my XML files
<?xml version="1.0" encoding="utf-8" ?>
<Funrun>
<Venue name="Roker Park">
<Runner charity="Cancer Research">
<Firstname>Roger</Firstname>
<Lastname>Malibu</Lastname>
<Sponsorship>550</Sponsorship>
</Runner>
<Runner charity="Arthritis UK">
<Firstname>Adam</Firstname>
<Lastname>White</Lastname>
<Sponsorship>340</Sponsorship>
</Runner>
</Venue>
</Funrun >
I need to be able to select the venue name and save it to a list. This is what I've got so far:
List<string> VenueNames = new List<string>();
var doc = XDocument.Load("XMLFile1.xml");
var doc2 = XDocument.Load("XMLFile2.xml");
var doc3 = XDocument.Load("XMLFile3.xml");
var combinedUnique = doc.Descendants("Venue")
.Union(doc2.Descendants("Venue"))
.Union(doc3.Descendants("Venue"));
foreach (var venuename in combinedUnique.Elements("Venue"))
{
VenueNames.Add(venuename.Attribute("name").Value));
}
The easiest way I would do it is by including Name and Charity within the XElements they belong to.
What I would recommend you do is first reformat your document so that it looks like this:
<Funrun>
<Venue>
<Name>Roker Park</Name>
<Runner1>
<charity>Cancer Research</charity>
<Firstname>Roger</Firstname>
<Lastname>Malibu</Lastname>
<Sponsorship>550</Sponsorship>
</Runner1>
<Runner2>
<charity>Arthritis UK</charity>
<Firstname>Adam</Firstname>
<Lastname>White</Lastname>
<Sponsorship>340</Sponsorship>
</Runner2>
</Venue>
</Funrun >
Note that you could get even simpler by combining all the elements under "Funrun" (example: "Venue") and just iterate through all of them without having to switch documents.
Next moving over to C#:
List<string> VenueNames = new List<string>();
var doc = XDocument.Load("XMLFile1.xml");
var doc2 = XDocument.Load("XMLFile2.xml");
var doc3 = XDocument.Load("XMLFile3.xml");
foreach (XElement element in doc.Root.Descendants("Venue"))
{
VenueNames.Add(element.Element("Name").Value.ToString());
}
//Copy paste this code for each document you would like to search through, though of course change "doc" to say, "doc2".
So just real quick, what this code will do is it will first open the Root element in the XDocument. It will find Decendants of that element with the name, "Name", and for each of those it will copy its value as a string into your list.
List<string> xmlFilePaths = new List<string>
{
#"Path\\SomeJson.txt",
#"Path\\SomeJson1.txt"
};
var venues = xmlFilePaths.Select(fp => XDocument.Load(fp).Descendants("Venue")?.FirstOrDefault()?.Attribute("name")?.Value).Distinct().ToList();

Getting the value from specific tag of a XML file in C# [duplicate]

This question already has answers here:
How does one parse XML files? [closed]
(12 answers)
Closed 7 years ago.
I'm starting working with XML files and I know little about it.
What I need is read the value from a certain tag of a XML file
<Tag>
<Name>PBAS</Name>
<ID>1</ID>
<Description>Array of sequence characters as edited by user</Description>
<Type>char</Type>
<Elements>163</Elements>
<Size>163</Size>
<Value>TCCGAACAAGCGGCGAGTGCTGGGCGAGTGGCCGCGGGGCTGTGGTCCTGTGCACGGTGATCGCAAGGGCCCCCGGGGCTTGCTGGTCTTCCCTAACGGTTCGTGGAACCCCCGAAGCTGGGGGCTGGCCAGGGGCTTAAGGAACCCTTCCTAAATTAACTAC</Value>
</Tag>
I need, in the example above, getting the string between the "Value"(the string TCCGA...) of the tag named "PBAS" with "ID 1".
But I need this value just from the tag named PBAS with "ID1", since the XML document has other "values" from other tags named differently.
Thanks a lot!
var yourval = XDocument.Load(filename)
.XPathSelectElement("//Tag[Name='PBAS' and ID='1']")
.Element("Value")
.Value;
or
var yourval = (string)XDocument.Load(filename)
.XPathSelectElement("//Tag[Name='PBAS' and ID='1']/Value");
or (using only Linq)
var yourval = XDocument.Load(filename)
.Descendants("Tag")
.Where(t => (string)t.Element("Name") == "PBAS")
.Where(t => (string)t.Element("ID") == "1")
.First()
.Element("Value")
.Value;
PS: Necessary namespaces: System.Xml, System.Xml.XPath, and System.Xml.Linq . Also Read about Linq2Xml and Xpath
The technology to select nodes from XML is called XPath. Basically you create a path of element names separated by / like
/Tag/Value
To specify conditions, put them in square brackets at the place from where you want to start the condition:
/Tag[./Name/text()="PBAS"][./ID/text()="1"]/Value
Above XPath is good for demonstration purposes, since it explains how it works. In practice, this would be simplified to
/Tag[Name="PBAS"][ID="1"]/Value
Code:
using System.Xml;
var doc = new XmlDocument();
doc.LoadXml(xml);
var nodes = doc.SelectNodes("/Tag[./Name/text()=\"PBAS\"][./ID/text()=\"1\"]/Value");
foreach (XmlElement node in nodes)
{
Console.WriteLine(node.InnerText);
}
Console.ReadLine();
You can use the below code:
string xmlFile = File.ReadAllText(#"D:\Work_Time_Calculator\10-07-2013.xml");
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(xmlFile);
XmlNodeList xnList = xmldoc.SelectNodes("/Tag");
string Value ="";
foreach (XmlNode xn in xnList)
{
string ID = xn["ID"].InnerText;
if(ID =="1")
{
value = xn["Value"].InnerText;
}
}

How to extract xml child element

I am trying to figure out the code to extract xml child (I think this is worded correctly) elements. I have searched and tried many samples but cannot find how to drill down to pick out the section I want and return the information I need. Maybe I all I need is someone to define the data I am trying to pull so I can read up on the issue, of course any code would be very helpful and I will figure it out from there. Thanks in advanced for any help!
Here is the xml file. I am trying to run an if statement to find the section named <STATISTICTYPE>PVCAP_CharactersSaved</STATISTICTYPE> and return the <JOBNAME>,<TIMEDELTA>,<VALUESUM>.
<?xml version="1.0" encoding="utf-8"?>
<PVCAPTURESTATISTICCONTAINTER xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PVCAPTUREJOBSTATISTICS>
<PVCAPTURESTATISTICSUMMARY>
<STATISTICTYPE>PVCAP_CharactersSaved</STATISTICTYPE>
<STATISTICNAME>Characters saved</STATISTICNAME>
<JOBID>24</JOBID>
<JOBNAME>HEAT FILES</JOBNAME>
<TIMEDELTA>422</TIMEDELTA>
<VALUESUM>25432</VALUESUM>
</PVCAPTURESTATISTICSUMMARY>
<PVCAPTURESTATISTICSUMMARY>
<STATISTICTYPE>PVCAP_CharactersSaved_NoMM</STATISTICTYPE>
<STATISTICNAME>Characters saved (no match and merge)</STATISTICNAME>
<JOBID>24</JOBID>
<JOBNAME>HEAT FILES</JOBNAME>
<TIMEDELTA>422</TIMEDELTA>
<VALUESUM>25432</VALUESUM>
</PVCAPTURESTATISTICSUMMARY>
</PVCAPTUREJOBSTATISTICS>
<DOCUMENTCOUNT>762</DOCUMENTCOUNT>
<PAGECOUNT>3194</PAGECOUNT>
<IMAGECOUNT>3194</IMAGECOUNT>
<VERSION>2.0</VERSION>
</PVCAPTURESTATISTICCONTAINTER>
You can use LINQ to XML, particularly the XElement class.
var element = XElement.Parse(xmlStr).Element("PVCAPTUREJOBSTATISTICS")
.Elements("PVCAPTURESTATISTICSUMMARY")
.First(c => c.Element("STATISTICTYPE").Value == "PVCAP_CharactersSaved")
var jobName = element.Element("JOBNAME").Value;
var timeDelta = element.Element("TIMEDELTA").Value;
var valueSum = element.Element("VALUESUM").Value;
You'll want to add in some error handling and whatnot here, but this should get you going in the right direction.
You can do something like this:
XElement res = XElement.Parse(xmlResult);
foreach(var elem in res.Element("PVCAPTUREJOBSTATISTICS").Elements("PVCAPTURESTATISTICSUMMARY"))
{
if (elem.Element("STATISTICTYPE").Value.Equals("PVCAP_CharactersSaved", StringComparison.Ordinal))
{
string jobName = elem.Element("JOBNAME").Value;
string timeDelta = elem.Element("TIMEDELTA").Value;
string valueSum = elem.Element("VALUESUM").Value;
}
}
You can use XDocument and LINQ-to-XML to do that quite easily, for example :
string xml = "your xml content here";
XDocument doc = XDocument.Parse(xml);
//or if you have the xml file instead :
//XDocument doc = XDocument.Load("path_to_xml_file.xml");
var result = doc.Descendants("PVCAPTURESTATISTICSUMMARY")
.Where(o => (string) o.Element("STATISTICTYPE") == "PVCAP_CharactersSaved")
.Select(o => new
{
jobname = (string) o.Element("JOBNAME"),
timedelta = (string) o.Element("TIMEDELTA"),
valuesum = (string) o.Element("VALUESUM")
});
foreach (var r in result)
{
Console.WriteLine(r);
}

C# - Linq to XML - Exclude elements from query

I have this XML file:
<MyXml>
<MandatoryElement1>value</MandatoryElement1>
<MandatoryElement2>value</MandatoryElement2>
<MandatoryElement3>value</MandatoryElement3>
<CustomElement1>value</CustomElement1>
<CustomElement2>value</CustomElement2>
<MyXml>
All 3 elements that are called 'MandatoryElementX' will always appear in the file. The elements called 'CustomElementX' are unknown. These can be added or removed freely by a user and have any name.
What I need is to fetch all the elements that are not MandatoryElements. So for the file above I would want this result:
<CustomElement1>value</CustomElement1>
<CustomElement2>value</CustomElement2>
I don't know what the names of the custom elements may be, only the names of the 3 MandatoryElements, so the query needs to somehow exclude these 3.
Edit:
Even though this was answered, I want to clarify the question. Here is an actual file:
<Partner>
<!--Mandatory elements-->
<Name>ALU FAT</Name>
<InterfaceName>Account Lookup</InterfaceName>
<RequestFolder>C:\Documents and Settings\user1\Desktop\Requests\ALURequests</RequestFolder>
<ResponseFolder>C:\Documents and Settings\user1\Desktop\Responses</ResponseFolder>
<ArchiveMessages>Yes</ArchiveMessages>
<ArchiveFolder>C:\Documents and Settings\user1\Desktop\Archive</ArchiveFolder>
<Priority>1</Priority>
<!--Custom elements - these can be anything-->
<Currency>EUR</Currency>
<AccountingSystem>HHGKOL</AccountingSystem>
</Partner>
The result here would be:
<Currency>EUR</Currency>
<AccountingSystem>HHGKOL</AccountingSystem>
You can define a list of mandatory names and use LINQ to XML to filter:
var mandatoryElements = new List<string>() {
"MandatoryElement1",
"MandatoryElement2",
"MandatoryElement3"
};
var result = xDoc.Root.Descendants()
.Where(x => !mandatoryElements.Contains(x.Name.LocalName));
Do you have created this xml or do you get it by another person/application?
If it's yours I would advise you not to number it. You can do something like
<MyXml>
<MandatoryElement id="1">value<\MandatoryElement>
<MandatoryElement id="2">value<\MandatoryElement>
<MandatoryElement id="3">value<\MandatoryElement>
<CustomElement id="1">value<\CustomElement>
<CustomElement id="2">value<\CustomElement>
<MyXml>
In the LINQ-Statement you don't need the List then.
Your question shows improperly formatted XML but I am assuming that is a typo and the real Xml can be loaded into the XDocument class.
Try this...
string xml = #"<MyXml>
<MandatoryElement1>value</MandatoryElement1>
<MandatoryElement2>value</MandatoryElement2>
<MandatoryElement3>value</MandatoryElement3>
<CustomElement1>value</CustomElement1>
<CustomElement2>value</CustomElement2>
</MyXml> ";
System.Xml.Linq.XDocument xDoc = XDocument.Parse(xml);
var result = xDoc.Root.Descendants()
.Where(x => !x.Name.LocalName.StartsWith("MandatoryElement"));
lets say TestXMLFile.xml will contain your xml,
XElement doc2 = XElement.Load(Server.MapPath("TestXMLFile.xml"));
List<XElement> _list = doc2.Elements().ToList();
List<XElement> _list2 = new List<XElement>();
foreach (XElement x in _list)
{
if (!x.Name.LocalName.StartsWith("Mandatory"))
{
_list2.Add(x);
}
}
foreach (XElement y in _list2)
{
_list.Remove(y);
}

Categories