Add XML node where element value equal n - c#

I have a XML file which looks like
<?xml version="1.0" encoding="utf-8"?>
<Orders>
<Order>
<OrderNumber>123</OrderNumber>
<ClientName>Name</ClientName>
<TotalOrderCost>50</TotalOrderCost>
<Products>
<Product>
<Name>Games</Name>
<Quantity>3</Quantity>
<Price>10</Price>
<TotalProductPrice>30</TotalProductPrice>
</Product>
<Product>
<Name>CDs</Name>
<Quantity>2</Quantity>
<Price>10</Price>
<TotalProductPrice>10</TotalProductPrice>
</Product>
</Products>
</Order>
<Order>
<OrderNumber>456</OrderNumber>
<ClientName>Name 2</ClientName>
<TotalOrderPrice>15</TotalOrderPrice>
<Products>
<Product>
<Name>Tea</Name>
<Quantity>1</Quantity>
<Price>15</Price>
<TotalProductPrice>15</TotalProductPrice>
</Product>
</Products>
</Order>
</Orders>
I have a form where the user selects an order and can add more products in it. I can output the correct XElement which looks like:
<Product>
<Name>Coffee</Name>
<Quantity>1</Quantity>
<Price>15</Price>
<TotalProductPrice>15</TotalProductPrice>
</Product>
How do I add this XElement under the products of an order user has selected? So if the user selects OrderNumer = 456 and adds the product using the form, the XElement goes under 456 order.
I have tried:
xmldoc2.Element("Orders").Element("Order").Element("Products").Add(addProduct);
xmldoc2.Save(orderFilePath);
which always adds the product to the first order on the XML and I can see the reason for it however I cannot see how I could add under the product under the order selected.

You should select order element to which you want to add new product:
int number = 456;
var order = xmldoc2.Element("Orders").Element("Order")
.FirstOrDefault(o => (int)o.Element("OrderNumber") == number);
// check if order not null
order.Element("Products").Add(addProduct);
You also can use XPath for selecting order:
var xpath = String.Format("//Order[OrderNumber[text()={0}]]", number);
var order = xmldoc2.XPathSelectElement(xpath);

Related

Select list of node by innertext. Issue XmlDocument

I have following Xml
<Main>
<Order Id="1262">
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod2</Name>
<Barcode>2345</Barcode>
</Product>
</Order>
<Order Id="1263">
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod2</Name>
<Barcode>2345</Barcode>
</Product>
</Order>
</Main>
XmlDocument xml=new XmlDocument();
xml.Load(path);
Now I want to select only nodes whose barcode is 1234 from Node whose orderId=1263. My code is
string OrderId="1262"
string ReadedBarcode ="1234"
XmlNode ONode = xml.SelectSingleNode("//Order[#Id='" + OrderId + "']");
XmlNodeList BarCodeNodeList = ONode.SelectNodes("//Product/Barcode[text()='" + ReadedBarcode + "']");
But I dont know why all the nodes from document having innertext 1234 are getting selected. that means even node from <Order Id="1263"> this node is getting selected.
Any Solutions?
This should do it
XmlDocument xml=new XmlDocument();
xml.Load(path);
string OrderId = "1262";
string ReadedBarcode = "1234";
XmlNodeList BarCodeNodeList = xml.SelectNodes("//Order[#Id='" + OrderId + "']"+"//Product/Barcode[text()='" + ReadedBarcode + "']");
Also, your XML is invalid, it is missing some start tags, it should be
<Main>
<Order Id="1262">
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod2</Name>
<Barcode>2345</Barcode>
</Product>
</Order>
<Order Id="1263">
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod2</Name>
<Barcode>2345</Barcode>
</Product>
</Order>
</Main>
I know you wrote that you are 'stuck' with XmlDocument, but the reason you gave sounded like a decision not based on the technical constraints, rather on preference. I believe in a tool-for-the-job, so please forgive me for writing a solution you may not like, but it might persuade you of the merits in using XDocument where you see the benefit.
The XML you posted was not syntactically correct, the sample below shows the corrections where I have added the missing Product starter nodes.
Here's what I would suggest, code written in LinqPad. The Dump() method just spits the variable out to a console. Also, I did not know which 'node' you wanted to find, so I am returning the Order node in this sample.
Cheers, Aaron
var doc = XDocument.Parse(#"
<Main>
<Order Id=""1262"">
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod2</Name>
<Barcode>2345</Barcode>
</Product>
</Order>
<Order Id=""1263"">
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod1</Name>
<Barcode>1234</Barcode>
</Product>
<Product>
<Name>Prod2</Name>
<Barcode>2345</Barcode>
</Product>
</Order>
</Main>
");
var barcode = "1234";
var orderId = "1263";
var found = (
from row in doc.Root.Descendants("Order")
where
row.Attribute("Id") != null &&
row.Attribute("Id").Value == orderId &&
row.Descendants("Barcode").Any(a => a.Value == barcode)
select row).ToList();
found.Dump();

Add XML element before last element using Linq

I need to add new element before the last element of the XML using Linq.
For example:
<?xml version="1.0" encoding="utf-8"?>
<products>
<product id="p1">
<name>Delta</name>
<price>800</price>
<country>Denmark</country>
</product>
<product id="p3">
<name>Alfa</name>
<price>1200</price>
<country>Germany</country>
</product>
</products>
New element <stock></stock> should be inserted before <country> element using Linq
// load the XML file into XDocument instance
var doc = XDocument.Load("sourceFile.xml");
// find all <country> elements
var countries = doc.Root.Elements("product").Elements("Country");
// add <stock /> before each <country> elements
foreach(var country in countries)
{
country.AddBeforeSelf(new XElement("stock"));
}
// save document to the file
doc.Save("sourceFile.xml");

Linq to Xml query to child nodes

<InventoryList>
<Product xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Id>1</Id>
<Name>Pizza Ristorante Hawaii</Name>
<Price>2.99</Price>
<VariableWeightPrice>€ 8,42 / kg</VariableWeightPrice>
<Brand>Dr.Oetker</Brand>
<PackageInfo>355 GR</PackageInfo>
<categoryString />
<PictureSmallFilename>1small.jpg</PictureSmallFilename>
<InformationTakenFrom>Jumbo</InformationTakenFrom>
<MarketItemUrl></MarketItemUrl>
<BarCode>4001724819608</BarCode>
<IsBlackListed>false</IsBlackListed>
<ItemLists>
<Item>
<ListName>in</ListName>
<Quantity>1</Quantity>
<QuantityWeight>0</QuantityWeight>
</Item>
<Item>
<ListName>out</ListName>
<Quantity>2</Quantity>
<QuantityWeight>0</QuantityWeight>
</Item>
</ItemLists>
</Product>
<Product xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Id>2</Id>
<Name>Produto 2</Name>
<Price>2.99</Price>
<VariableWeightPrice>€ 5,55 / kg</VariableWeightPrice>
<Brand>Dr.Oetker</Brand>
<PackageInfo>355 GR</PackageInfo>
<categoryString />
<PictureSmallFilename>1small.jpg</PictureSmallFilename>
<InformationTakenFrom>Jumbo</InformationTakenFrom>
<MarketItemUrl></MarketItemUrl>
<BarCode>4001724819608</BarCode>
<IsBlackListed>false</IsBlackListed>
<ItemLists>
<Item>
<ListName>out</ListName>
<Quantity>1</Quantity>
<QuantityWeight>0</QuantityWeight>
</Item>
</ItemLists>
</Product>
</InventoryList>
thanks in advance for your help.
I have this xml database
i want to return all products that have the ListName = "out", but this query i´m trying it´s only returning the second product, and i need it to return the first and the second product.
var _queryItems = from c in xml.Descendants("Product")
where
c.Element("ItemLists").Element("Item").Element("ListName").Value == "out"
select c;
thanks :)
Right now you just check the first Item element, instead you want to check if any Item's ListName matches "out":
var _queryItems = from c in xml.Descendants("Product")
where c.Element("ItemLists")
.Elements("Item").Any( x=> x.Element("ListName").Value == "out")
select c;

linq to xml navigate through xml c#

I have some XML and need to be able to read the data within.
A sample of the XML is
<?xml version="1.0" ?>
<ConsumeLeadRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<LeadType>Mortgage</LeadType>
<LeadXml>
<ns1:LeadAssigned xmlns:ns1="http://YaddaYadda" xmlns:ns0="http://YaddaYadda" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ns0:Lead>
<Reference>1234</Reference>
<Product>
<Mnemonic>Mortgage</Mnemonic>
<Description>Mortgage Leads</Description>
<SubType>Other</SubType>
</Product>
<ExtendedInfo>
<Mortgage>
<MortgageValue>75000</MortgageValue>
<MortgageValueLowerBound>1</MortgageValueLowerBound>
<MortgageValueUpperBound>500</MortgageValueUpperBound>
<PropertyValue>100000</PropertyValue>
<PropertyValueLowerBound>1</PropertyValueLowerBound>
<PropertyValueUpperBound>500</PropertyValueUpperBound>
<Adverse>false</Adverse>
<FirstTime>false</FirstTime>
</Mortgage>
</ExtendedInfo>
<Applicants>
<Applicant1>
<Title>Mr</Title>
<Forename>SampleForename</Forename>
<Surname>SampleSurname</Surname>
<DateOfBirth>1903-02-01</DateOfBirth>
<Smoker>false</Smoker>
<TelephoneNumbers>
<TelephoneNumber>
<Number>01244123456</Number>
<Type>Mobile</Type>
</TelephoneNumber>
</TelephoneNumbers>
<EmailAddresses>
<EmailAddress>
<Email>test#moneysupermarket.com</Email>
<Type>Business</Type>
</EmailAddress>
</EmailAddresses>
<Addresses>
<Address>
<Street>Sample Street</Street>
<District>Sample District</District>
<Town>Sample Town</Town>
<County>Sample County</County>
<Postcode>CH53UZ</Postcode>
<Type>Home</Type>
</Address>
</Addresses>
</Applicant1>
</Applicants>
</ns0:Lead>
<Assignment>
<Price>20</Price>
<AssignmentDateTime>2010-02-01T00:00:00</AssignmentDateTime>
<Subscription>
<Reference>1234</Reference>
<Subscriber>
<Title>Mr</Title>
<Forename>SampleForename</Forename>
<Surname>SampleSurname</Surname>
</Subscriber>
</Subscription>
<Account>
<Reference>1234</Reference>
<CompanyName>Sample Company</CompanyName>
</Account>
<LeadType>SampleLeadType</LeadType>
<TerritoryName>UNITED KINGDOM</TerritoryName>
</Assignment>
</ns1:LeadAssigned>
</LeadXml>
<AuthenticationUsername>Username</AuthenticationUsername>
<AuthenticationPassword>Password</AuthenticationPassword>
</ConsumeLeadRequest>
Using Linq to XML how do i navigate to the items?
Thanks
Sp
I have tried a few things like
XDocument Leads = XDocument.Load(#"C:\Users\Steven.Pentleton\AppData\Local\Temporary Projects\PAALeadImport\PAAExmple.xml");
var Lead = (from L in Leads.Descendants("Lead")
select new { LeadType = (string)L.Element("Reference") }).ToList();
var S = Lead.First();
string T = S.LeadType;
Are you looking for XDcoument or XElement in linq
Namespace: using System.Xml.Linq;
I guess you are looking for a Linq To Xml guide

Need a Nested LINQ to XML query help

i have a XML file as follows:
<?xml version="1.0" encoding="utf-8" ?>
<publisher>
<name>abc</name>
<link>http://</link>
<description>xyz</description>
<category title="Top">
<item>
<title>abc</title>
<link>http://</link>
<pubDate>1</pubDate>
<description>abc</description>
</item>
<item>
<title>abc</title>
<link>http://</link>
<pubDate>2</pubDate>
<description>abc</description>
</item>
</category>
<category title="Top2">
<item>
<title>abc</title>
<link>http://</link>
<pubDate>1</pubDate>
<description>abc</description>
</item>
<item>
<title>abc</title>
<link>http://</link>
<pubDate>2</pubDate>
<description>abc</description>
</item>
</category>
</publisher>
I need to write a LINQ to XML query in C# which returns everything under a "category" tag based on the value of attribute provided. I have tried the following code but it gives me error. Any help will be appreciated:
System.Xml.Linq.XElement xml = System.Xml.Linq.XElement.Parse(e.Result);
IEnumerable<string> items = from category in xml.Elements("category")
where category.Attribute("title").Value == "Top"
select category.ToString();
IEnumerable<string> items = from category in xml.Descendants("category")
where category.Attribute("title").Value == "Top"
select category.ToString();
Of course, that's going to give you a list with one string in it. If you want just the string in it:
var items = (from category in xml.Descendants("category")
where category.Attribute("title").Value == "Top"
select category.ToString()).First();
But, if you want to continue processing the XML, you probably really want it as a XElement object:
var items = (from category in xml.Descendants("category")
where category.Attribute("title").Value == "Top"
select category).First();

Categories

Resources