LINQ to XML query from querystring - c#

I need to create xml files based on querystring values.
My xml file:
<Products>
<Product>
<Name>Name</Name>
<Category>Books</Category>
<SubCategory>Drama</SubCategory>
</Product>
<Product>
<Name>Name</Name>
<Category>Books</Category>
<SubCategory>Action</SubCategory>
</Product>
<Product>
<Name>Name</Name>
<Category>Paper</Category>
<SubCategory></SubCategory>
</Product>
So if i type ?filter=Books,Paper i need to select Product where Categorycontains value from querystring.
Then if i type ?filter=Books,Paper&filter2=Drama i still need Product where Category contains filter1 but if Product element containsSubCategory that containsfilter2 i need to select just those.
So with: ?filter=Books,Paper&filter2=Drama i need to get xml that looks like this:
<Products>
<Product>
<Name>Name</Name>
<Category>Books</Category>
<SubCategory>Drama</SubCategory>
</Product>
<Product>
<Name>Name</Name>
<Category>Paper</Category>
<SubCategory></SubCategory>
</Product>
</Products>
Also some products may have empty SubCategory element. I don't know if that is important.
My query looks like this:
var items = from el in SimpleStreamAxis(esysPath, "Product")
where filter.Contains(el.Element("Category").Value.Trim())
where filter1.Contains(el.Element("SubCategory").Value.Trim())
select new
{
ProductID = el.Element("ID").Value,
Name = el.Element("Name").Value,
Price = el.Element("Price").Value,
Picture = el.Element("Picture").Value
};
This is selecting all Product elements where filter1 contains SubCategory.
So can anyone point me in to right direction on how to write this query.
Thanks.

This should get you started in the right direction, it will find all products where the Category element is either Book or Paper
List<string> categories = new List<string() {"Book", "Paper"};
XDocument doc = XDocument.Parse("Your xml string");
var products = doc.Descendants("Product")
.Where(el => categories.Contains(el.Element("Category").Value));

Related

How to merge multiple XML files with data in same format in it to a single XML file with all data together using C#.NET?

I have a blob (XYZ) that receives multiple XML files in same format. See below
XML file 1:
<Product>
<ID>001</ID>
<Name>John</Name>
<Designation>Developer</Designation>
</Product>
XML file 2:
<Product>
<ID>002</ID>
<Name>Peter</Name>
<Designation>Tester</Designation>
</Product>
XML file 3:
<Product>
<ID>003</ID>
<Name>Arun</Name>
<Designation>Support</Designation>
</Product>
XML file 4:
<Product>
<ID>004</ID>
<Name>Swetha</Name>
<Designation>Analyst</Designation>
</Product>
XML file 5:
<Product>
<ID>005</ID>
<Name>Gokul</Name>
<Designation>Maintainence</Designation>
</Product>
I need to merge all these files to a single XML file like below and put into another blob (ABC).
Merged XML file:
<xml>
<Product>
<ID>001</ID>
<Name>John</Name>
<Designation>Developer</Designation>
</Product>
<Product>
<ID>002</ID>
<Name>Peter</Name>
<Designation>Tester</Designation>
</Product>
<Product>
<ID>003</ID>
<Name>Arun</Name>
<Designation>Support</Designation>
</Product>
<Product>
<ID>004</ID>
<Name>Swetha</Name>
<Designation>Analyst</Designation>
</Product>
<Product>
<ID>005</ID>
<Name>Gokul</Name>
<Designation>Maintainence</Designation>
</Product>
</xml>
I may need one like this.
What I have tried so far is below one.
using (var jw = new XmlTextWriter(sw)) //sw holds the o/p location to store the merged files
{
jw.WriteStartElement("root");
int i = 0;
int c = list.Count();
foreach (var item in list)
{
if (i > 0)
await jw.WriteRawAsync("\r\n");
var blobdata = await OutputContainerService.GetContentAsync(input.InputLocation + "/" + item);
await jw.WriteRawAsync(blobdata);
i++;
}
jw.WriteEndElement();
await jw.FlushAsync();
}
How could I achieve this using C#.NET?
Option 1 :
Create Product Class
Populate the Product object with values by de-serializing the xml
Add the product object to List
Serialize the List
Option 2:
read the xml to XML Document
populate the product xml as xml node
Add the xml nodes to xml documents

How do to read specific data by the id from xml in ASP.Net

I wanted to select a specific data based on its id and here are the example of the xml
<?xml version="1.0" encoding="ISO-8859-1"?>
<productdetails>
<product>
<Id>1</Id>
<product_name>banana</product_name>
<product_price>5.00</product_price>
<product_description>its banana</product_description>
<product_quantity>12</product_quantity>
</product>
<product>
<Id>2</Id>
<product_name>mango</product_name>
<product_price>10.00</product_price>
<product_description>its mango</product_description>
<product_quantity>12</product_quantity>
</product>
<product>
<Id>3</Id>
<product_name>orange</product_name>
<product_price>3.00</product_price>
<product_description>its orange</product_description>
<product_quantity>1</product_quantity>
</product>
<product>
<Id>4</Id>
<product_name>apple</product_name>
<product_price>4.00</product_price>
<product_description>its apple</product_description>
<product_quantity>1</product_quantity>
</product>
</productdetails>
What im trying to do is store them back in a different but temporary xml file to then be calculated in GridView.
Hope I understood your query correctly. You could search for specific data based on its Id using Linq. For example,
var root = XElement.Parse(xmlString);
var idToSearch = 1;
var result= root.Elements("product")
.Where(x=>Convert.ToInt32(x.Element("Id").Value)==idToSearch)
.Select(x=>new
{
ProductName=x.Element("product_name").Value,
Price=x.Element("product_price").Value
});

How to get xml node value based on attribute value c# , asp.net?

how to get xmlnode value based on attribute value in C#.
<Products>
<Error>0</Error>
<Product link="OWN">
<ProductCode>CA</ProductCode>
<ProductType>Account</ProductType>
<ProductSubtype>Current Account</ProductSubtype>
<ProductDescriptionEng>Current Account</ProductDescriptionEng>
<ProductNumber>1234567</ProductNumber>
<ProductCurrency></ProductCurrency>
<ProductCurrencyCode>01</ProductCurrencyCode>
<ProductBalance>899293.003</ProductBalance>
<LoanRef></LoanRef>
<OldLoanRef></OldLoanRef>
<ProductStandardID>00010001</ProductStandardID>
<OldLoanRef></OldLoanRef>
<ProductStatusCode>00</ProductStatusCode>
<ProductStatus>OPEN</ProductStatus>
<ProductCategory>Deposit Account</ProductCategory>
</Product>
</Product>
in the above example i would like to get value of Product Link "OWN" based on passing attribute value (1234567) 1234567.
I have tried following code but it doesn't return value "OWN" from 'Product link" node.
string _accountsXml = GetProducts();
_xmlDoc.LoadXml(_accountsXml);
_productLinkType = _xmlDoc.SelectSingleNode(string.Format("//Products[../ProductNumber = '{0}']", prodNumber));
You do have to add code to get element's attribute value there, possibly minding the case when the right element was not found. Plus be careful with the element names - both in the xpath expression and in the XML.
The following test code would have "OWN" in the link variable:
var doc = XDocument.Parse(#"<?xml version=""1.0""?>
<Products>
<Error>0</Error>
<Product link=""Global""/>
<Product link=""OWN"">
<Some/>
<ProductNumber>1234567</ProductNumber>
<Nodes/>
</Product>
<Product link=""External"">
<ProductNumber>777</ProductNumber>
</Product>
</Products>");
var id = 1234567;
var link = doc
.XPathSelectElement($"//Product[ProductNumber = '{id}']")
?.Attribute("link")
?.Value;
Console.WriteLine($"Product link: {link ?? "not found"}");
Try this
_productLinkType = _xmlDoc.SelectSingleNode(string.Format("//Products[..//ProductNumber = '{0}']", prodNumber));
or
var xDoc = XDocument.Load(_accountsXml);
var productLinkType = xDoc.XPathSelectElement(string.Format("//Products[..//ProductNumber = '{0}']", prodNumber)).Element("Product").Attribute("link").Value;
The closing tag in your example is Product it should be Products

how to get value of child nodes in xml one by one

How can i read asin and its value from This xml file.
i have multiple product in this xml file.
This two products asin i want to get.
XDocument xdoc = XDocument.Load(#"D:\Product\WriteText2.xml");
XElement match = xdoc.Root.Element("GetMatchingProductForIdResult");
foreach(XElement product in match.Elements("Products"))
{
XElement asin = product.Element("Identifiers").Element("MarketplaceASIN").Element("ASIN");
string asinValue = asin.Value;
}
<GetMatchingProductForIdResult Id="619659000431" IdType="UPC" status="Success">
<Products>
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>A21TJRUUN4KGV</MarketplaceId>
<ASIN>B002U1ZBG0</ASIN>
</MarketplaceASIN>
</Identifiers>
</Product>
</Products>
</GetMatchingProductForIdResult>
<GetMatchingProductForIdResult Id="190198462411" IdType="UPC" status="Success">
<Products>
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>A21TJRUUN4KGV</MarketplaceId>
<ASIN>B073Q5R6VR</ASIN>
</MarketplaceASIN>
</Identifiers>
</Product>
</Products>
</GetMatchingProductForIdResult>
You can use System.Xml.Linq:
XDocument xdoc = XDocument.Load("file.xml");
XElement match = xdoc.Element("GetMatchingProductForIdResult");
foreach(XElement product in match.Elements("Products")){
XElement asin = product.Element("Identifiers")
.Element("MarketplaceASIN").XElement("ASIN");
string asinValue = asin.Value;
}

How can be this xml parsed in efficient way?

I am beginner in C#.
Simple Example of bigger case:
Input:
<?xml version="1.0" encoding="utf-8"?>
<products>
<product>
<id>1</id>
<name>John</name>
</product>
<product>
<id>2</id>
<name>Tom</name>
</product>
<product>
<id>3</id>
<name>Sam</name>
</product>
</products>
</xml>
Output(for id=1):
<id>2</id>
<name>Tom</name>
My part code try psedocode:
XDocument doc=XDocument.Parse(".............");
var els= doc.Descendants("product");
foreach(e in els){
node=e.Element("id");
if(2==node.Value){
return e;
}
}
Please help,
Thanks
Currently your xml file is not well-formatted - remove closing </xml> tag from your file to make it valid. And here is the query:
int id = 1;
XDocument xdoc = XDocument.Load(path_to_xml);
var product = xdoc.Descendants("product")
.Where(p => (int)p.Element("id") == id)
.SingleOrDefault();
This query will return whole <product> element or null if match not found.
Also I believe product name will be enough for you to select (because you already have product id):
var name = xdoc.Descendants("product")
.Where(p => (int)p.Element("id") == id)
.Select(p => (string)p.Element("name"))
.SingleOrDefault();
Returns Tom for id = 2
This will return the product (as in your question) not the id
var product = doc.XPathSelectElement("//product[id and id[text() = '1']]");
You might be looking for XPath:
root.XPathSelectElements(#"//products/product/id[text()='2']")
Edit To the comment: Directly getting the name: //products/product/id[text()='2']/../name
See full example
using System.Xml.Linq;
using System.Xml.XPath;
public class Program
{
public static void Main(string[] args)
{
var doc = XDocument.Parse(XML);
foreach(var n in doc.Root.XPathSelectElements(
#"//products/product/id[text()='2']"))
{
System.Console.WriteLine("Not that hard: '{0}'", n.Parent.Element("name").Value);
}
// Direct query for name:
foreach(var n in doc.Root.XPathSelectElements(
#"//products/product/id[text()='2']/../name"))
{
System.Console.WriteLine("Directly: '{0}'", n.Value);
}
}
private const string XML =
#"<?xml version=""1.0"" encoding=""utf-8""?>
<products>
<product>
<id>1</id>
<name>John</name>
</product>
<product>
<id>2</id>
<name>Tom</name>
</product>
<product>
<id>3</id>
<name>Sam</name>
</product>
</products>";
}
Printing:
Not that hard: 'Tom'
Directly: 'Tom'

Categories