Descendants not found even if they exist in XDocument in C# - c#

I am having problems with getting descendant with specific name. I have hugh XML that basically is made of lots of this elements:
<?xml version="1.0" encoding="utf-8"?>
<Search_Results xmlns="https://support.bridgerinsight.lexisnexis.com/downloads/xsd/4.5/OutputFile.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://support.bridgerinsight.lexisnexis.com/downloads/xsd/4.5/OutputFile.xsd https://support.bridgerinsight.lexisnexis.com/downloads/xsd/4.5/OutputFile.xsd">
<Entity Record="28" ResultID="12460985">
<GeneralInfo>
<EntityType>Individual</EntityType>
<Name>Jón Jónsson</Name>
<DOB>01/01/0001</DOB>
<DOBParsed />
<AccountID>ABS-ASSOC-10-109</AccountID>
<IDLabel>Account ID</IDLabel>
<IDNumber>ABS-ASSOC-10-109</IDNumber>
<AddressType>Current</AddressType>
<PostalCode>Somalia</PostalCode>
</GeneralInfo>
<RecordDetailInfo>
<EntityType>Individual</EntityType>
<SearchDate>2016-05-13 09:53:50Z</SearchDate>
<Origin>Automatic Batch</Origin>
<FirstName>Jón</FirstName>
<LastName>Jónsson</LastName>
<FullName>Jón Jónsson</FullName>
<AdditionalInfo>
<Type>Date of Birth</Type>
<Information>01/01/0001</Information>
</AdditionalInfo>
<Addresses>
<Type>Current</Type>
<PostalCode>Somalia</PostalCode>
</Addresses>
<Identifications>
<Type>Account ID</Type>
<Number>ABS10-109</Number>
</Identifications>
</RecordDetailInfo>
<WatchList>
<Match ID="1">
<EntityName>Jonsson</EntityName>
<EntityScore>96</EntityScore>
<BestName>Jonsson, Jon Orn</BestName>
<BestNameScore>96</BestNameScore>
<FileName>WorldCompliance - Full.BDF</FileName>
<SourceDate>2016-05-11 05:01:00Z</SourceDate>
<DistributionDate>2016-05-12 14:59:39Z</DistributionDate>
<ResultDate>2016-05-13 09:53:50Z</ResultDate>
<EntityUniqueID>WX0003219444</EntityUniqueID>
<MatchDetails>
<Entity Type="2">
<Number>3219444</Number>
<Date>9/3/2012</Date>
<Reason>International</Reason>
<CheckSum>69185</CheckSum>
<Gender>Male</Gender>
<Name>
<First>Jon Orn</First>
<Last>Jonsson</Last>
<Full>Jon Orn Jonsson</Full>
</Name>
<Notes>Source.</Notes>
<Addresses>
<Address ID="1" Type="4">
<Country>Iceland</Country>
</Address>
</Addresses>
<IDs>
<ID ID="1" Type="27">
<Number>3219444</Number>
</ID>
</IDs>
<Descriptions>
<Description ID="1" Type="10">
<Value>Honorary Consul of Iceland in Saskatchewan, Canada</Value>
<Notes>Starting 2002 Ending 2014</Notes>
</Description>
<Description ID="2" Type="22">
<Value>Link to WorldCompliance Online Database</Value>
<Notes>Jonsson, Jon Orn | https://members.worldcompliance.com/metawatch2.aspx?id=e0399c29-7c5e-4674-874c-f36fdb19052e</Notes>
</Description>
<Description ID="3" Type="22">
<Value>Sources of Record Information</Value>
<Notes>http://brunnur.mfa.is/interpro/utanr/HBvefur.nsf/Pages/IslSendiradIsl?OpenDocument&amp | CountryNr=1(Canada)&amp | Lang=44') | http://www.international.gc.ca/protocol-protocole/assets/pdfs/Diplomatic_List.pdf | http://www.inlofna.org/Elfros/newsletter%20January%202010.pdf | http://publications.gc.ca/collections/Collection/E12-3-2002E.pdf | http://www.onlygolfnews.com/golf-canada-saskatchewan/saskatchewan-golf-first-fort-lacrosse-ted-brandon-over-new-last-snow.htm | http://www.ops.gov.sk.ca/Consular-Officers</Notes>
</Description>
</Descriptions>
</Entity>
</MatchDetails>
</Match>
</WatchList>
</Entity>
</Search_Results>
I am trying to reach all elements with name: Entity and later I want to go through all of them and get values from their descendants with name "Reason".
But non of the Entity elements is found with this line:
var entityList = xmlDoc.Descendants(nameSpace + "Entity").ToList();
This is a whole method I am using:
public static void GetIBANAndBicValuesFromXML(XDocument xmlDoc)
{
var reasons = new List<string>();
XNamespace nameSpace =
"https://support.bridgerinsight.lexisnexis.com/downloads/xsd/4.5/";
var entityList = xmlDoc.Descendants(nameSpace + "Entity").ToList();
if (entityList != null)
{
foreach (var reason in entityList.Select(entity => entity.Elements(nameSpace + "Reason"))
.Where(reasonsList => reasonsList != null).SelectMany(reasonsList => reasonsList))
{
string reasonValue = reason.Value;
reasons.Add(reasonValue);
}
}
}
And this is a call to this method:
private static void Main(string[] args)
{
var xmlFile = "C:\\temp\\indi2.xml";
var x = XDocument.Load("C:\\temp\\Individuals.xml");
XMLParse.GetIBANAndBicValuesFromXML(x);
}
I have tried namespace like this as well:
"https://support.bridgerinsight.lexisnexis.com/downloads/xsd/4.5/OutputFile.xsd"
But no success.
Anybody sees what I am doing wrongly?

You can use Linq to filter with LocalName:
string fileName = "1.txt";
var xDoc = XDocument.Load(fileName);
var neededElements = xDoc.Descendants().Where(x => x.Name.LocalName == "Entity");
Console.WriteLine("Found {0} Entitys", neededElements.Count());
foreach(var el in neededElements)
{
Console.WriteLine(el);
}

Related

How to get value of same nodes in XML in c#

I want to get the value of artist (Bob Dylan) for title "Greatest Hits" in the xml below
<?xml version="1.0" encoding="ISO-8859-1"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<price>10.90</price>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<price>10.0</price>
</cd>
<cd>
<title>Greatest Hits</title>
<artist>Bob Dylan</artist>
<price>10.90</price>
</cd>
</catalog>
Adapt it as you need ...
using System.Xml;
static void GetArtistFromXml()
{
var xml = "<?xml version=\"1.0\" encoding=\"ISO - 8859 - 1\"?><catalog><cd><title>Empire Burlesque</title><artist>Bob Dylan</artist><price>10.90</price></cd><cd><title>Hide your heart</title><artist>Bonnie Tyler</artist><price>10.0</price></cd><cd><title>Greatest Hits</title><artist>Bob Dylan</artist><price>10.90</price></cd></catalog>";
var xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml);
var artistElement = xmlDocument.DocumentElement.SelectSingleNode("//cd[title[text()=\"Greatest Hits\"]]/artist");
Console.WriteLine(artistElement.InnerText);
}
It is better to use LINQ to XML API. It is available in the .Net Framework since 2007.
c#
void Main()
{
const string filename = #"e:\Temp\AmeyP.xml";
XDocument xdoc = XDocument.Load(filename);
string artist = xdoc.Descendants("cd")
.Where(x => x.Element("title").Value.Equals("Greatest Hits"))
.Elements("artist").FirstOrDefault()?.Value;
Console.WriteLine(artist);
}
Output
Bob Dylan

Iterate through nested XML nodes and save it to a list in asp.net c#

I have a xml file with nested xml nodes. i need to loop through the nodes and save the innertext to list. The xml format is like below:
<xml>
<record>
</record>
<Actions>
<Action Name= "name1">
<screen>
<subAction></SubAction>
</screen>
</Action>
<Action Name = "name2">
<screen Description= "info">
<subAction>
<object>
<name> user </name>
<type> string </type>
<variable> ram </variable>
</object>
<object>
<name> user1 </name>
<type> string1 </type>
<variable> ram1 </variable>
</object>
</subAction>
</screen>
<Screen Description= "info1">
<subAction>
<object>
</object>
</subAction>
</Screen>....goes on
</Action>
</Actions>
</xml>
I need to check if Action == name2, loop through and get all the object types in list. I am not able to get nested nodes.
Below is the code i have tried:
XmlNodeList NodesPro = xmlDoc.SelectNodes("/xml/Actions/Action");
foreach (XmlNode pronode in NodesPro)
{
bool flag = false;
if (pronode.Attributes["Name"].Value == "name2")
{
//Dont know how to proceed. Please help
}
It is better to use LINQ to XML API. It is available in the .Net Framework for more than a decade.
The XML provided is not well-formed. I had to fix it.
It is not clear what is your desired output.
I copied #Sajid's class as a placeholder for data.
c#
void Main()
{
XDocument xsdoc = XDocument.Parse(#"<xml>
<record>
</record>
<Actions>
<Action Name='name1'>
<screen>
<subAction></subAction>
</screen>
</Action>
<Action Name='name2'>
<screen Description='info'>
<subAction>
<object>
<name>user</name>
<type>string</type>
<variable>ram</variable>
</object>
<object>
<name>user1</name>
<type>string1</type>
<variable>ram1</variable>
</object>
</subAction>
</screen>
<Screen Description='info1'>
<subAction>
<object>
</object>
</subAction>
</Screen>....goes on</Action>
</Actions>
</xml>");
List<ActionObject> objects3 = new List<ActionObject>();
foreach (var el in xsdoc.Descendants("Action")
.Where(x => x.Attribute("Name").Value.Equals("name2")))
{
objects3 = el.Descendants("object")
.Select(p => new ActionObject()
{
Name = p.Element("name")?.Value,
Type = p.Element("type")?.Value,
Variable = p.Element("variable")?.Value
}).ToList();
}
}
public class ActionObject
{
public string Name { get; set; }
public string Type { get; set; }
public string Variable { get; set; }
}
I prefer #Yitzhak solution, but if you want to use XmlDocument, you could try the following :
1 - Create class ActionObject:
public class ActionObject
{
public string Name { get; set; }
public string Type { get; set; }
public string Variable { get; set; }
}
2 - Xml
string xml2 = #"
<xml>
<record>
</record>
<Actions>
<Action Name= 'name1'>
<screen></screen>
<subAction></subAction>
</Action>
<Action Name = 'name2'>
<screen Description= 'info'>
<subAction>
<object>
<name> user </name>
<type> string </type>
<variable> ram </variable>
</object>
<object>
<name> user1 </name>
<type> string1 </type>
<variable> ram1 </variable>
</object>
</subAction>
</screen>
<Screen Description= 'info1'>
<subAction>
<object></object>
</subAction>
</Screen>
</Action>
</Actions>
</xml>";
3 - Code that get objects from xml:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(xml2);
List<ActionObject> objects = new List<ActionObject>();
XmlNodeList actions = xmlDocument.DocumentElement.SelectNodes("/xml/Actions/Action");
foreach (XmlElement actionNode in actions)
{
if (actionNode.Attributes["Name"].Value != "name2")
continue;
foreach(XmlNode objectNode in actionNode.SelectNodes("./screen/subAction/object"))
{
ActionObject actionObject = new ActionObject
{
Name = objectNode.SelectSingleNode("name").InnerText.Trim(),
Type = objectNode.SelectSingleNode("type").InnerText.Trim(),
Variable = objectNode.SelectSingleNode("variable").InnerText.Trim(),
};
objects.Add(actionObject);
}
}
I hope you find this helpful.

c# Merging two XMLs giving error

I am trying to merge two XMLs with same structure but different data into one.
I am getting this error: A node of type Document cannot be added to content.
Below is my code
var productElements =
testGroupProvider.GetTestGroup().ProductTests.Select(
productTest => new XElement(xNamespace + "Product",
new XElement(xNamespace + "ExternalId", productTest.ProductNameKey),
new XElement(xNamespace + "Name", testGroupProvider.GetProductName(productTest)),
new XElement(xNamespace + "ImageUrl", ChoiceBaseHostName + GetProductImageUrl(productTest, TargetDatabase))));
var root = new XDocument(
new XElement(xNamespace + "Feed",
new XAttribute("xmlns", xNamespace),
new XAttribute("name", BVFeedsName),
new XAttribute("incremental", "true"),
new XAttribute("extractDate", DateTime.Now.ToString("o")),
new XElement(xNamespace + "Categories",
new XElement(xNamespace + "Category",
new XElement(xNamespace + "ExternalId", testGroupProvider.GetProductGroup().Id),
new XElement(xNamespace + "Name", testGroupProvider.GetProductGroup().Name),
testGroupProvider.GetTestGroup().Name),
new XElement(xNamespace + "Products", productElements)));
var filePath = #"D:\testXML\test.xml";
XElement xml = XElement.Load(filePath);
xml.Add(root);
xml.Save(filePath);
Can anyone tell me what i am doing wrong.
This is the XML structure in test.xml
<?xml version="1.0" encoding="utf-8"?>
<Feed xmlns="http://www.bazaarvoice.com/xs/PRR/ProductFeed/5.6" name="Choice" incremental="true" extractDate="2016-07-12T15:24:44.5732750+10:00">
<Categories>
<Category>
<ExternalId>{09B3B4FB-F5CF-4522-BE96-4C4B535580C3}</ExternalId>
<Name>Cereal and muesli</Name>
</Category>
</Categories>
<Products>
<Product>
<ExternalId>coles-almond-hazelnut-macadamia-cluster-fusions</ExternalId>
<Name>Coles Almond, Hazelnut & Macadamia Cluster Fusions</Name>
<ImageUrl></ImageUrl>
</Product>
</Products>
</Feed>
The second XML has the same structure with different products
<?xml version="1.0" encoding="utf-8"?>
<Feed xmlns="http://www.bazaarvoice.com/xs/PRR/ProductFeed/5.6" name="Choice" incremental="true" extractDate="2016-07-12T15:24:44.5732750+10:00">
<Categories>
<Category>
<ExternalId>{12}</ExternalId>
<Name>cat1</Name>
</Category>
</Categories>
<Products>
<Product>
<ExternalId>Id</ExternalId>
<Name>Ccoles</Name>
<ImageUrl></ImageUrl>
</Product>
</Products>
</Feed>
I want to combine them like below
<?xml version="1.0" encoding="utf-8"?>
<Feed xmlns="http://www.bazaarvoice.com/xs/PRR/ProductFeed/5.6" name="Choice" incremental="true" extractDate="2016-07-12T15:24:44.5732750+10:00">
<Categories>
<Category>
<ExternalId>{09B3B4FB-F5CF-4522-BE96-4C4B535580C3}</ExternalId>
<Name>Cereal and muesli</Name>
</Category>
<Category>
<ExternalId>{12}</ExternalId>
<Name>cat1</Name>
</Category>
</Categories>
<Products>
<Product>
<ExternalId>coles-almond-hazelnut-macadamia-cluster-fusions</ExternalId>
<Name>Coles Almond, Hazelnut & Macadamia Cluster Fusions</Name>
<ImageUrl></ImageUrl>
</Product>
<Product>
<ExternalId>Id</ExternalId>
<Name>Ccoles</Name>
<ImageUrl></ImageUrl>
</Product>
</Products>
</Feed>
A xml document must have only one root.
Working with the documents you attached, you can replace the xml.Add(root); with the following (i.e. it will add each node under one root to the other xml root)
foreach (var child in root.Root.Elements())
{
xml.Element(child.Name.ToString()).Add(child.Nodes());
}
Edit - A further generalization
You can generalize the above code using a Merge extension of 2 XElements so that it reads as follows
foreach (var child in root.Elements())
{
xml.Element(child.Name.ToString()).Merge(child, xNamespace + "ExternalId");
}
Having defined the extension
public static void Merge(this XElement root1, XElement root2, XName element_id)
{
root1.Add(root2.Elements().Except(root1.Elements(), new MyComparer(element_id)));
}
with a xml comparer
public class MyComparer : IEqualityComparer<XElement>
{
private XName _element_id;
public MyComparer(XName element_id)
{
_element_id = element_id;
}
public bool Equals(XElement x, XElement y)
{
return x.Element(_element_id).Value.Equals(y.Element(_element_id).Value);
}
public int GetHashCode(XElement el)
{
return el.Element(_element_id).Value.GetHashCode();
}
}
Select correct nodes to add and correct nodes to be added.
var filePath = #"D:\testXML\test.xml";
XElement xml = XElement.Load(filePath);
var xmlCategories = xml.Descendants("Categories").First();
var rootCategories = root.Descendants("Category");
xmlCategories.Add(rootCategories);
var xmlProducts = xml.Descendants("Products").First();
var rootProducts = root.Descendants("Product");
xmlProducts.Add(rootProducts);
xml.Save(filePath);
Be crystal clear what you are doing.
Try this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication2
{
class Program
{
const string FILENAME1 = #"c:\temp\test1.xml";
const string FILENAME2 = #"c:\temp\test2.xml";
static void Main(string[] args)
{
XDocument doc1 = XDocument.Load(FILENAME1);
XDocument doc2 = XDocument.Load(FILENAME2);
XElement category1 = doc1.Descendants().Where(x => x.Name.LocalName == "Categories").FirstOrDefault();
XElement category2 = doc2.Descendants().Where(x => x.Name.LocalName == "Categories").FirstOrDefault();
category1.Add(category2.Descendants());
XElement product1 = doc1.Descendants().Where(x => x.Name.LocalName == "Products").FirstOrDefault();
XElement product2 = doc2.Descendants().Where(x => x.Name.LocalName == "Products").FirstOrDefault();
product1.Add(product2.Descendants());
}
}
}
Try this, sorry about the VB
'second is The second XML has the same structure with different products
Dim combined As XElement = New XElement(test) 'create copy of test.xml
combined.<Categories>.LastOrDefault.Add(second.<Categories>.Elements)
combined.<Products>.LastOrDefault.Add(second.<Products>.Elements)
or
'if test can be used to combine then
test.<Categories>.LastOrDefault.Add(second.<Categories>.Elements)
test.<Products>.LastOrDefault.Add(second.<Products>.Elements)
The result is
<Feed name="Choice" incremental="true" extractDate="2016-07-12T15:24:44.5732750+10:00" xmlns="http://www.bazaarvoice.com/xs/PRR/ProductFeed/5.6">
<Categories>
<Category>
<ExternalId>{09B3B4FB-F5CF-4522-BE96-4C4B535580C3}</ExternalId>
<Name>Cereal and muesli</Name>
</Category>
<Category>
<ExternalId>{12}</ExternalId>
<Name>cat1</Name>
</Category>
</Categories>
<Products>
<Product>
<ExternalId>coles-almond-hazelnut-macadamia-cluster-fusions</ExternalId>
<Name>Coles Almond, Hazelnut & Macadamia Cluster Fusions</Name>
<ImageUrl></ImageUrl>
</Product>
<Product>
<ExternalId>Id</ExternalId>
<Name>Ccoles</Name>
<ImageUrl></ImageUrl>
</Product>
</Products>
</Feed>
The test data I used is
Dim test As XElement =
<Feed xmlns="http://www.bazaarvoice.com/xs/PRR/ProductFeed/5.6" name="Choice" incremental="true" extractDate="2016-07-12T15:24:44.5732750+10:00">
<Categories>
<Category>
<ExternalId>{09B3B4FB-F5CF-4522-BE96-4C4B535580C3}</ExternalId>
<Name>Cereal and muesli</Name>
</Category>
</Categories>
<Products>
<Product>
<ExternalId>coles-almond-hazelnut-macadamia-cluster-fusions</ExternalId>
<Name>Coles Almond, Hazelnut & Macadamia Cluster Fusions</Name>
<ImageUrl></ImageUrl>
</Product>
</Products>
</Feed>
Dim second As XElement =
<Feed xmlns="http://www.bazaarvoice.com/xs/PRR/ProductFeed/5.6" name="Choice" incremental="true" extractDate="2016-07-12T15:24:44.5732750+10:00">
<Categories>
<Category>
<ExternalId>{12}</ExternalId>
<Name>cat1</Name>
</Category>
</Categories>
<Products>
<Product>
<ExternalId>Id</ExternalId>
<Name>Ccoles</Name>
<ImageUrl></ImageUrl>
</Product>
</Products>
</Feed>
The XElements can be loaded like this
test = XElement.Load("PATH")
second = XElement.Load("second PATH")
and saved like this
test.Save("PATH")
second.Save("second PATH")
combined.Save("combined PATH")

How to turn one XML record with sub nodes into multiple records without XSLT or SQL

I need to figure out how to turn one XML record with sub nodes into multiple records using C#. Yes, I know it would be easier to do this using XSLT but that isn't an option. I have an XML file that must be modified to be used by 5 different uses so I need a common starting point.
Forgive my lack of understanding but nothing I can find seems to go in this direction. Everything goes in the other direction. Here is a sample of my code and file.
The source file.
<inventoryitems>
<inventoryitem>
<id>11101</id>
<displayname>LG HAMBURGER PATTY</displayname>
<basemeasure>EACH</basemeasure>
<reportingmeasure>EACH</reportingmeasure>
<measures>
<measure>
<name>CS</name>
<factor>1.000000</factor>
<isactive>1</isactive>
</measure>
<measure>
<name>ST</name>
<factor>8.000000</factor>
<isactive>1</isactive>
</measure>
<measure>
<name>EACH</name>
<factor>120.000000</factor>
<isactive>1</isactive>
</measure>
</measures>
<categories>
<category>
<name>MEATS</name>
</category>
</categories>
<locations />
<skus />
</inventoryitem>
<inventoryitem>
<id>11102</id>
<displayname>SM HAMBURGER PATTY</displayname>
<basemeasure>EACH</basemeasure>
<reportingmeasure>EACH</reportingmeasure>
<measures>
<measure>
<name>ST</name>
<factor>6.000000</factor>
<isactive>1</isactive>
</measure>
<measure>
<name>CS</name>
<factor>1.000000</factor>
<isactive>1</isactive>
</measure>
<measure>
<name>EACH</name>
<factor>96.000000</factor>
<isactive>1</isactive>
</measure>
</measures>
<categories>
<category>
<name>MEATS</name>
</category>
</categories>
<locations />
<skus />
</inventoryitem>
<inventoryitem>
<id>11202</id>
<displayname>BREAD SM BUN 4</displayname>
<basemeasure>EACH</basemeasure>
<reportingmeasure>EACH</reportingmeasure>
<measures>
<measure>
<name>TR</name>
<factor>1.000000</factor>
<isactive>1</isactive>
</measure>
<measure>
<name>EACH</name>
<factor>30.000000</factor>
<isactive>1</isactive>
</measure>
</measures>
<categories>
<category>
<name>BAKERY</name>
</category>
</categories>
<locations />
<skus />
</inventoryitem>
</inventoryitems>
What I need to get would look something like this.
<data>
<row InventoryItemId="11201" ItemDescription="BREAD LG BUN 5" CategoryName="BAKERY" Measure="TR" />
<row InventoryItemId="11201" ItemDescription="BREAD LG BUN 5" CategoryName="BAKERY" Measure="EACH" />
</data>
I was able to write the code to mode the value to an attribute when the is only one node but I am at a loss on what to do when there is a sub node with multiple values.
invlist = results.Substring(results.IndexOf("<inventoryitems>"), (results.IndexOf("</inventoryitemsresponsedata>") - results.IndexOf("<inventoryitems>")));
XmlDocument doc = new XmlDocument();
XmlNode nd = doc.CreateNode("element", "data", "");
doc.AppendChild(nd);
//XmlNode rw = doc.CreateNode("element", "row", "");
//nd.AppendChild(rw);
var invitems = new XmlDocument { InnerXml = invlist };
XmlNode result = doc.ImportNode(invitems.DocumentElement, true);
nd.AppendChild(result);
XmlNodeList ndList = doc.SelectNodes("data/inventoryitems/inventoryitem");
foreach (XmlNode id in ndList)
{
XmlNode idnode = id.SelectSingleNode("id");
if (idnode != null)
{
XmlNode rw = doc.CreateNode("element", "row", "");
nd.AppendChild(rw);
var attribute = doc.CreateAttribute("InventoryItemId");
attribute.Value = idnode.InnerXml;
var Description = doc.CreateAttribute("ItemDescription");
Description.Value = id.SelectSingleNode("displayname").InnerXml;
rw.Attributes.Append(attribute);
rw.Attributes.Append(Description);
}
XmlNodeList msList = id.SelectNodes("measures/measure");
foreach (XmlNode mes in msList)
{
XmlNode msnode = mes.SelectSingleNode("name");
if (msnode != null)
{
var attribute = doc.CreateAttribute("Measure");
attribute.Value = msnode.InnerXml;
//rw.Attributes.Append(attribute);
mes.Attributes.Append(attribute);
}
}
}
Any help would be appreciated.
Update: This is what I am getting.
<data>
<row InventoryItemId="11201" ItemDescription="BREAD LG BUN 5" CategoryName="BAKERY" />
<inventoryitem>
<measures>
<measure Measure="TR"></measure>
<measure Measure="EACH"></measure>
</measures>
<locations />
<skus />
</inventoryitem>
</data>
I figured it out. By wrapping each node inside a row node loop I get the results I was looking for.
var item = idnode.InnerXml;
XmlNodeList rwList = doc.SelectNodes(String.Format("data/row[#InventoryItemId='{0}']",item));
var rwCount = rwList.Count;
foreach (XmlNode rw in rwList)
{
XmlNodeList msList = id.SelectNodes("measures/measure");
foreach (XmlNode mes in msList)
{
XmlNode msnode = mes.SelectSingleNode("name");
{
var attribute = doc.CreateAttribute("Measure");
attribute.Value = msnode.InnerXml;
if (rwCount > 0)
{
rw.Attributes.Append(attribute);
rwCount--;
}
else
{
XmlNode clonenode = rw.Clone();
clonenode.Attributes.Append(attribute);
nd.AppendChild(clonenode);
}
}
}
}

Finding and Filtering XML Data

I have an XML document here:
<?xml version="1.0" encoding="utf-8" ?>
<CATALOG>
<CD>
<TITLE>Empire Burlesque</TITLE>
<ARTIST>Bob Dylan</ARTIST>
<COUNTRY>USA</COUNTRY>
<COMPANY>Columbia</COMPANY>
<PRICE>10.90</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Hide your heart</TITLE>
<ARTIST>Bonnie Tyler</ARTIST>
<COUNTRY>UK</COUNTRY>
<COMPANY>CBS Records</COMPANY>
<PRICE>9.90</PRICE>
<YEAR>1988</YEAR>
</CD>
<CD>
<TITLE>Test Title 1</TITLE>
<ARTIST>Test Name 1</ARTIST>
<COUNTRY>Test Country 1</COUNTRY>
<COMPANY>Test Company 1</COMPANY>
<PRICE>100.00</PRICE>
<YEAR>1985</YEAR>
</CD>
<CD>
<TITLE>Test Title 3</TITLE>
<ARTIST>Test Name 3</ARTIST>
<COUNTRY>Test Country 3</COUNTRY>
<COMPANY>Test Company 3</COMPANY>
<PRICE>1.99</PRICE>
<YEAR>1984</YEAR>
</CD>
<CD>
<TITLE>Test Title 2</TITLE>
<ARTIST>Test Name 2</ARTIST>
<COUNTRY>Test Country 2</COUNTRY>
<COMPANY>Test Company 2</COMPANY>
<PRICE>19.99</PRICE>
<YEAR>1985</YEAR>
</CD>
</CATALOG>
What I am trying to do is find all the CDs that have a year of 1985. I'm very new to LINQ to XML and I have no idea what I'm doing. Because most internet resources are very specific example, I'm having trouble applying it to my example.
Here's the C# that I've coded so far:
namespace ReadingXML
{
class Program
{
static void Main(string[] args)
{
XElement xelement = XElement.Load("..\\..\\music.xml");
IEnumerable<XElement> music = xelement.Elements();
/*// Read the entire XML
foreach (var item in catalogues)
{
Console.WriteLine(item);
}
Console.ReadLine();*/
var query = from item in music.Descendants("CD")
select new { year = item.Element("YEAR").Equals(1985) };
foreach (var item in query)
Console.WriteLine(item.ToString());
Console.ReadLine();
}
}
}
Can someone please tell me how I can achieve what I'm trying to do and/or why my code isn't functioning?
XDocument X = XDocument.Load(#"XMLFileLocation");
var CDsIn1985 = X.Element("CATALOG").Elements("CD").Where(E => E.Element("YEAR").Value == "1985");
foreach (var item in CDsIn1985)
{
Console.WriteLine(String.Format("Title : {0}, Artist : {1}", item.Element("TITLE").Value, item.Element("ARTIST").Value));
}
Another away is to use String Interpolation
foreach (var item in CDsIn1985)
{
Console.WriteLine(String.Format($"Title : {item.Element("TITLE").Value}, Artist : { item.Element("ARTIST").Value}"));
}

Categories