I want to get the specific node from my XML response using Linq
My Xml:
<DataSet xmlns="http://www.bnr.ro/xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bnr.ro/xsd nbrfxrates.xsd">
<Header>
<Publisher>National Bank of Romania</Publisher>
<PublishingDate>2016-12-30</PublishingDate>
<MessageType>DR</MessageType>
</Header>
<Body>
<Subject>Reference rates</Subject>
<OrigCurrency>RON</OrigCurrency>
<Cube date="2016-01-04">
<Rate currency="AED">1.1272</Rate>
<Rate currency="EUR">4.5169</Rate>
<Rate currency="BGN">2.3094</Rate>
<Rate currency="HUF" multiplier="100">1.4320</Rate>
<Rate currency="INR">0.0622</Rate>
<Rate currency="JPY" multiplier="100">3.4798</Rate>
<Rate currency="KRW" multiplier="100">0.3481</Rate>
<Rate currency="MDL">0.2107</Rate>
</Cube>
<Cube>
...
</Cube>
</Body>
</DataSet>
So i want to position on the cube which have date equals with a date paramater. Then i want to gate the rate value which has currency equals with "EUR".
I am trying to do this with Linq but it's not working
My Linq code:
WebClient webClient = new WebClient();
string url = "http://www.bnr.ro/files/xml/years/nbrfxrates" + year + ".xml";
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
XDocument systemXml = XDocument.Load(response.GetResponseStream());
XElement cube = (from cubeElement in systemXml.Elements("Cube")
where cubeElement.Attribute("date").ToString().Equals(data)
select cubeElement).Single();
XElement rate = (from rateElement in cube.Elements("Rate")
where rateElement.Attribute("currency").ToString().Equals("EUR")
select rateElement).Single();
My problem is that systemXml.Elements("Cube") returns null.
This is my url for web request http://www.bnr.ro/files/xml/years/nbrfxrates2017.xml
It looks like you need the namespace.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication55
{
class Program
{
static void Main(string[] args)
{
string url = "http://www.bnr.ro/files/xml/years/nbrfxrates2017.xml";
XDocument systemXml = XDocument.Load(url);
XNamespace ns = ((XElement)systemXml.FirstNode).GetDefaultNamespace();
DateTime date = DateTime.Parse("2017-01-05");
var results = systemXml.Descendants(ns + "Cube")
.Where(x => ((DateTime)x.Attribute("date") == date))
.Descendants(ns + "Rate")
.Where(x => (string)x.Attribute("currency") == "EUR")
.FirstOrDefault();
var value = (decimal)results;
}
}
}
Your Root element is DataSet,which has childs and one of them is Body,which has childs Cube. Also you need to specify the namespace of the element which is {http://www.bnr.ro/xsd}. So here is working LINQ for you.
XDocument systemXml = XDocument.Load(path);
XElement cube = (from cubeElement in systemXml.Elements("{http://www.bnr.ro/xsd}DataSet").Elements("{http://www.bnr.ro/xsd}Body").Elements("{http://www.bnr.ro/xsd}Cube")
where cubeElement.Attribute("date").Value.Equals("2017-01-03")
select cubeElement).Single();
XElement rate = (from rateElement in cube.Elements("{http://www.bnr.ro/xsd}Rate")
where rateElement.Attribute("currency").Value.Equals("EUR")
select rateElement).Single();
Enjoy it!!
Related
Here is the XML structure:
<root>
<listOfItems>
<item>
<lineItem>1</lineItem>
<itemDetail>
<partNum>A1</partNum>
<color>red</color>
<qty>4</qty>
</itemDetail>
</item>
<item>
<lineItem>2</lineItem>
<itemDetail>
<partNum>B2</partNum>
<color>blue</color>
<qty>2</qty>
</itemDetail>
</item>
<item>
<lineItem>3</lineItem>
<itemDetail>
<partNum>C3</partNum>
<color>green</color>
<qty>1</qty>
</itemDetail>
</item>
</listOfItems>
</root>
Knowing that the partNum is B2, how would I be able to clone the entire item B2 belongs to so I have 2 identical B2 items.
You could use the CloneNode function to copy the node and AppendChild to attach it to the relevant place in the hierarchy.
// find the node
var target = doc.SelectSingleNode("root/listOfItems/item/itemDetail/partNum[text()='B2']");
// clone
var clonedNode = target.ParentNode.CloneNode(true);
// attach
target.ParentNode.ParentNode.AppendChild(clonedNode);
Here is a System.Xml.Linq solution.
//Load the XML Document
XDocument xdoc = XDocument.Load(xDocPath);
//Find the XMLNode
XElement xB2 = xdoc.Root.Element("listOfItems").Elements("item").FirstOrDefault(it => it.Element("itemDetail").Element("partNum").Value.Equals("B2"));
//Clone the XMLNode
XElement xB2Copy = new XElement(xB2);
The XElement xB2 is linked to the xdoc.
The XElement xB2Copy is not linked to xdoc.
You would have to add it first, here are some examples.
xdoc.Root.Element("listOfItems").Add(xB2Copy);
xB2.AddAfterSelf(xB2Copy);
xB2.AddBeforeSelf(xB2Copy);
Try following :
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication166
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XElement listOfItems = doc.Descendants("listOfItems").FirstOrDefault();
XElement itemB = listOfItems.Elements("item").Where(x => x.Descendants("partNum").Any(y => (string)y == "B2")).FirstOrDefault();
listOfItems.Add(XElement.Parse(itemB.ToString()));
}
}
}
I am trying to convert the XML attribute structure to XML tag structure.for example
<company>
<Name value="SomeCompany" /name>
<Count value ="500"/>
</Company>
to
<Company>
<Name>SomeCompany</name>
<EmployeeCount> 500<EmployyeCount>
</Company>
Here issue is input XML attribute structure is Dynamic.We don't know the exact schema of that.
I have tried to convert the input xml schema into json object(serializing) using Newtonsoft And able to convert the property names from count to Employe count.
But I am unable to convert the same json into xml tag structure(Deserializing).
{ XmlDocument infodoc = new XmlDocument();
infodoc.Load(#"C:\Users\dummy\desktop\test.xml");
string jsonText = JsonConvert.SerializeXmlNode(infodoc);
UpadtedXML h = JsonConvert.DeserializeObject<UpadtedXML
(jsonText);
}
Json is in this format:
{"Company":{"Name":{"#value":"someCompany"},"EmployeeCount":{"#value":"500"}
Expected result is like :
<Company>
<Name>SomeCompany</name>
<EmployeeCount> 500<EmployyeCount>
</Company>
The following code should work with any complex xml file. I'm using Xml Linq :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication124
{
class Program
{
static void Main(string[] args)
{
string input =
"<Company>\n" +
"<Name value=\"SomeCompany\"> </Name>\n" +
"<Count value =\"500\"/>\n" +
"</Company>";
XDocument doc = XDocument.Parse(input);
List<XElement> nodes = doc.Descendants().ToList();
for (int i = nodes.Count - 1; i >= 0; i--)
{
XElement node = nodes[i];
if ((string)node.Attribute("value") != null)
{
node.ReplaceWith(new XElement(node.Name.LocalName, new object[] {
node.Attributes().Where(x => x.Name.LocalName != "value"),
(string)node.Attribute("value"),
node.DescendantNodes()
}));
}
}
}
}
}
I am trying to find specific nodes in xml using XDocument. The xml also has a namespace which am importing.
Below is the xml specs
<?xml version="1.0" encoding="UTF-8"?>
<tns:response xmlns:tns="http://amazon.com/amazonservices">
<tns:responseDirect>
<tns:responseExtract>
<tns:A>ExtractName</tns:A>
</tns:responseExtract>
<tns:responses>
<tns:Name>Response1</tns:Name>
<tns:Include>No</tns:Include>
</tns:responses>
<tns:responses>
<tns:Name>Response2</tns:Name>
<tns:Include>Yes</tns:Include>
</tns:responses>
<tns:responses>
<tns:Name>Response3</tns:Name>
</tns:responses>
</tns:responseDirect>
I want to retrieve all responses and also only those nodes which have Include nodes present.
I am trying below code to fetch it but I am getting none of the nodes.
XDocument document = XDocument.Parse(xml);
var name = from nm in document.Elements("responses")
select nm;
Can anyone let me know how to fix the issue?I need to only fetch the response node.
Thanks in Advance
Try following :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
XDocument doc = XDocument.Load(FILENAME);
XNamespace ns = doc.Root.GetNamespaceOfPrefix("tns");
var results = doc.Descendants(ns + "responses")
.Where(x => x.Elements(ns + "Include").Any())
.Select(x => new {
include = (string)x.Element(ns + "Include"),
name = (string)x.Element(ns + "Name")
}).ToList();
}
}
}
I am using .net 4.0 winforms. In my application a have config file (config.xml), on this file i have lots nodes and child nodes, all are different, i want to select specific node and nodes inside the selected node.
I tried lots of solutions but not succeed.
Thanks in advance for your help.
This should give you the correct result:-
XDocument doc = XDocument.Load(#"XMLFilePath");
XNamespace ns = "http://schemas.datacontract.org/2004/07/Silvio.Settings";
var result = doc.Root.Element(ns + "maintenance_anomalies")
.Descendants(ns + "nom_operation")
.Select(x =>
new
{
NomOperation = (string)x,
statutList = x.Parent.Element(ns + "statuts")
.Elements(ns + "statut")
.Select(z => (string)z).ToList()
}).ToList();
Approach:
From the Xdocument object select the root node which is Main. From this select the Element maintenance_anomalies by including the Namespace associated with it. From there you can select all the descendants of nom_operation and fetch it's value. To find all statut inside nom_operation go back to parent node which is operation and from there select all statut elements.
You can also project a Type instead of anonymous type.
Getting following output:-
I had a couple of issues with your xml. First there is an invalid character so instead of using the Load method. There is also a namespace issue so I used Where method to get the tag maintenance_anomalies.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
namespace ConsoleApplication53
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
string file = File.ReadAllText(FILENAME);
XDocument doc = XDocument.Parse(file);
XElement maintenance_anomalies = doc.Descendants().Where(x => x.Name.LocalName == "maintenance_anomalies").FirstOrDefault();
XNamespace ns = maintenance_anomalies.Name.Namespace;
var results = maintenance_anomalies.Elements(ns + "operation").Select(x => new{
nom_operation = x.Element(ns + "nom_operation").Value,
statut = string.Join(",",x.Descendants(ns + "statut").Select(y => y.Value).ToArray())
}).ToList();
}
}
}
The line below should let u access the node u requested. Use this is your class using System.Xml;
XmlDocument XmlDocObj = new XmlDocument();
XmlNode UserNameNode = XmlDocObj.SelectSingleNode("maintenance_anomalies");
I am storing a xml in a string and using Xdocument i am parsing the string to xml from that i need to get xml element values and using that values i need to insert it in db. Any help would be appreciated.
XML:
<ListInventorySupplyResponse xmlns="http://mws.amazonaws.com/FulfillmentInventory/2010-10-01/">
- <ListInventorySupplyResult>
- <InventorySupplyList>
- <member>
<SellerSKU>043859634910</SellerSKU>
<FNSKU>X000IA4045</FNSKU>
<ASIN>B005YV4DJO</ASIN>
<Condition>NewItem</Condition>
<TotalSupplyQuantity>10</TotalSupplyQuantity>
<InStockSupplyQuantity>10</InStockSupplyQuantity>
- <EarliestAvailability>
<TimepointType>Immediately</TimepointType>
</EarliestAvailability>
<SupplyDetail />
</member>
</InventorySupplyList>
</ListInventorySupplyResult>
- <ResponseMetadata>
<RequestId>d50af29d-f203-4efc-a864-1725a59ded97</RequestId>
</ResponseMetadata>
</ListInventorySupplyResponse>
Code:
XDocument xd = XDocument.Parse(a);
string Sku = xd.Element();
var ASIN = xd.Descendants("ASIN");
var Condition = xd.Descendants("Condition");
var TotalSupplyQuantity = xd.Descendants("TotalSupplyQuantity");
You should use the xml namespace http://mws.amazonaws.com/FulfillmentInventory/2010-10-01/
var xDoc = XDocument.Parse(xml);
XNamespace ns = "http://mws.amazonaws.com/FulfillmentInventory/2010-10-01/";
var condition = (string)xDoc.Descendants(ns + "Condition").First();
OR
you can search for Tag Condition in any xml namespace
var condition2 = (string)xDoc.Descendants()
.First(d => d.Name.LocalName == "Condition");
OR
you can use XPath to get Condition in any xml namespace
var condition3 = (string)xDoc.XPathSelectElement("//*[local-name()='Condition']");
Use this:
string value = xd.Root.Element("SellerSKU").Value;