My goal is to be able to retrieve the value of <Cdtr><Id> from this XML file:
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns="urn:com.firmaname:response.002">
<DocId>1261076951</DocId>
<CreateDtTm>2016-11-23T14:53:23.938Z</CreateDtTm>
<ResponseCd>OK</ResponseCd>
<Dbtr>
<Id>debtorId</Id>
<Name>debtorName</Name>
</Dbtr>
<Cdtr>
<Id>creditorId</Id>
<Name>creditorName</Name>
</Cdtr>
</Document>
Note that this file 2 <Id> nodes, so I must specify the exact path to the node. The result should be 'creditorId'.
My code is:
XNamespace ns = "urn:com.firmaname:response.002";
var results = requestMessage.Descendants(ns + "Id").First().Value;
But this will return 'debtorId'. I've searched here to find a way to retrieve an exact path, but they all seem to involve using Xpath with XElement. When using XElement I run into trouble with the namespace. All of the suggestions I find are about using XDocument...
I would still use XDocument and select the Cdtr node, then the Id node within it.
One hack you can do with namespaces if you are confident you don't need them is to use <element>.Name.LocalName.
XDocument doc = XDocument.Load("<path to xml");
XNamespace ns = "urn:com.firmaname:response.002";
var creditorid = doc.Descendants().Elements()
.Where(e => e.Name == ns + "Cdtr").Elements()
.First(e => e.Name == ns + "Id");
Update using LocalName
var creditorid = doc.Descendants().Elements()
.Where(e => e.Name.LocalName == "Cdtr").Elements()
.First(e => e.Name.LocalName == "Id");
This works, however you should use the namespace if you can.
Related
I have this xml document, where I want to read documenturl where innertext ends with .xml
<Root>
<hits>
<total>4</total>
<max_score />
<hits>
<_index>offentliggoerelser-prod-20161006</_index>
<_type>offentliggoerelse</_type>
<_id>urn:ofk:oid:23640715</_id>
<_score />
<_source>
<dokumenter>
<dokumentUrl>url.pdf</dokumentUrl>
<dokumentMimeType>application/pdf</dokumentMimeType>
<dokumentType>KONCERNREGNSKAB_FOR_OVERLIGGENDE_MODER</dokumentType>
</dokumenter>
<dokumenter>
<dokumentUrl>url.xml</dokumentUrl>
<dokumentMimeType>application/xml</dokumentMimeType>
<dokumentType>AARSRAPPORT</dokumentType>
</dokumenter>
<dokumenter>
<dokumentUrl>url.pdf</dokumentUrl>
<dokumentMimeType>application/pdf</dokumentMimeType>
<dokumentType>AARSRAPPORT</dokumentType>
</dokumenter>
</_source>
<sort>1490355849989</sort>
</hits>
</hits>
</Root>
I am trying to read dokumentUrl that ends with '.xml' only.
I try to use LINQ
XDocument mydoc = XDocument.Load(file);
XDocument xPlatformXml = new XDocument(mydoc);
XElement xel = xPlatformXml.Element("_source")
.Elements("dokumenter")
.Where(x => x.Element("dokumentUrl").Value == ".xml")
.SingleOrDefault();
but it does not work, can anyone pls help me
You can check if you have the descendants node that has value ends with .xml
XDocument mydoc = XDocument.Load(file);
XDocument xPlatformXml = new XDocument(mydoc);
XElement xel = xPlatformXml.Root.Descendants()
.Where(x => x.Name == "dokumentUrl" && x.Value.EndsWith(".xml"))
.SingleOrDefault();
Try this:
XDocument xPlatformXml = new XDocument(mydoc);
XElement xel = xPlatformXml.Element("_source")
.Elements("dokumenter")
.Where(x => x.Element("dokumentUrl").Value.EndsWith(".xml"))
.SingleOrDefault();
When using the Element method you must specify the entire path from the document root to the desired nodes. For example:
var xel = xPlatformXml.Element("Root")
.Element("hits")
.Element("hits")
.Element("_source")
.Elements("dokumenter")
.Elements("dokumentUrl")
.SingleOrDefault(x => x.Value.EndsWith(".xml"));
Or you can use the Descendants method. It is more concise, but may affect performance.
var xel2 = xPlatformXml.Descendants("dokumentUrl")
.SingleOrDefault(x => x.Value.EndsWith(".xml"));
Hi i was fiddeling around with xml files and i notised something i have a bit problem of solving.
I have a Xml that starts with a root node and then has another child node that can change name for example:
<root>
<Child1>
</root>
So given that "Child1" can be changed to "Child2" or "Child3" i made this linq be able to extract the name from whatever comes my way.
first:
XElement root = XElement.Parse(xml);
var childType = root.Descendants().First(x => x.Name == "Child1" || x.Name == "Child2"|| x.Name == "Child3").Name;
So when i have my xml without a namespace, as shown above, it workes fine, i manage to extract the name from the node tag.
But when i have a namespace into the root tag it throws an error:
<root xmlns="namespace">
<Child1>
</root>
That xml going through the same linq, throws:
Sequence contains no matching element
Your root element has a namespace defined (xmlns="namespace") thus all child elements are associated with the same namespace. I.e. Child1 element will be in the same namespace, and its name will contain both namespace prefix and local name ("Child1"). So you can either specify full name when searching for Child1 element:
var ns = root.GetDefaultNamespace();
var childType = root.Descendants()
.First(x => x.Name == ns +"Child1" || x.Name == ns + "Child2"|| x.Name == ns + "Child3")
.Name;
Or you can look for x.Name.LocalName (but I don't recommned this approach, though it's unlikely you will have Child1 elements from another namespace).
Note: your Child element does not have closing tag (probably it's a misprint)
Further reading: Xml Namespaces
Trying to get the value for the "title" node from this XML -> http://feeds.feedburner.com/dotnetshoutout-published
I am using this code:
var d = XDocument.Load("http://feeds.feedburner.com/dotnetshoutout-published");
var node = d.Root.Descendants().Where(x => x.Name == "title").FirstOrDefault();
Always returns null. Making me crazy, any assistance is appreciated.
I guess you have an Xml Namespace on your elements.If so, your element name won't be just title, it will be namespace + title.Instead you should check the LocalName :
var node = d.Root.Descendants().Where(x => x.LocalName == "title").FirstOrDefault();
Or, you can look at the namespace of your elements and create an XNamespace and use it to fetch elements:
XNamespace ns = "yournamespace";
var node = d.Root.Descendants(ns + "title").FirstOrDefault();
You can read the documentation to find more info about how to deal with xml namespaces.
I have an xml whose root has namespaces like
<root version="2.0" xsi:schemaLocation="http://www.sample.org/schemas/2009 http://www.sample1.org/schemas/2009/railML-2.0/railML.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dc="http://xyz/elements/1.1/" xmlns="http://www.abcd.org/schemas/2009">
I am able to retrieve the value of xmlns using
var xdoc = XDocument.Load(XmlToParse);
Console.WriteLine(xdoc.Root.Name.NamespaceName);
but how can i get the values of other namespaces in root i.e. value of
xsi
dc
schemaLocation
Before parsing I need to verify these namespaces so i need these values.
how to do it?
can it be done by linq how?
var q = xdoc.Root.Attributes()
.Where(x => x.IsNamespaceDeclaration)
.Select(x => new {Prefixes = x.Name.LocalName, ns = x.Value});
EDIT:
More Ways: Get namespaces from an XML Document with XPathDocument and LINQ to XML
I have this XML document:
<?xml version="1.0" encoding="utf-8"?>
<directoryresponse xmlns="https://www.sisow.nl/Sisow/REST" version="1.0.0">
<directory>
<issuer>
<issuerid>01</issuerid>
<issuername>ABN Amro Bank</issuername>
</issuer>
<issuer>
<issuerid>02</issuerid>
<issuername>ASN Bank</issuername>
</issuer>
</directory>
</directoryresponse>
And this does not work:
var banks = doc.Descendants("issuer").Select(x =>
new Bank(Convert.ToInt32(x.Element("issuerid").Value), x.Element("issuername").Value)).ToList();
But when I manual remove the directoryresponse xml namespace
xmlns="https://www.sisow.nl/Sisow/REST" it works! The namespace url is a 404. So why doesn't the xdoc ignore the namespace if it's a 404?
This also does not work: var banks = doc.Elements().Where(e => e.Name.LocalName == "issuer" ).Select(...
The main question is: how can I modify my code so that it ignores the 404 namespace?
The URL itself is irrelevant here - it's just a token for the namespace, really. I don't believe LINQ to XML will try to fetch it.
However, you need to use it to construct the XName to search for:
XNamespace ns = "https://www.sisow.nl/Sisow/REST";
var banks = doc.Descendants(ns + "issuer")
.Select(x => new Bank((int) x.Element(ns + "issuerid"),
(string) x.Element(ns + "issuername"))
.ToList();