Linq to XML with Namespace Prefix Not Working - c#

I have been working from Scott Allen's Puralsight course on Linq Fundamentals and this linked section describes reading xml with Namespace prefixes, yet I'm not able to make this work.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<OutboundEvent
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:abb.com:assetsuite:IF:Event http://apifw/devifa/xml/GeneralLedger/GeneralLedger.Publish.Event.V940.xsd"
xmlns="urn:abb.com:assetsuite:IF:Event"
xmlns:hdr="urn:abb.com:assetsuite:IF:Header"
xmlns:bo="urn:abb.com:assetsuite:IF:BO"
xmlns:boe="urn:abb.com:assetsuite:IF:IFExtension"
>
...
<bo:BusinessObject>
...
</bo:BusinessObject>
</OutboundEvent>
I should be getting a single XElement returned from the following code, yet I am not:
var document = XDocument.Load(path);
var bo = (XNamespace)"urn:abb.com:assetsuite:IF:BO";
var businessobjects =
from elements in document.Element("OutboundEvent")?.Elements(bo + "BusinessObject")
?? Enumerable.Empty<XElement>()
select elements;

The OutboundEvent node is in a namespace but your code references it as if it wasn't. It is in the urn:abb.com:assetsuite:IF:Event namespace.
XNamespace ns = "urn:abb.com:assetsuite:IF:Event";
XNamespace bo = "urn:abb.com:assetsuite:IF:BO";
var businessObjects =
document.Elements(ns + "OutboundEvent").Elements(bo + "BusinessObject");

Shouldn't you define and use the default namespace for OutboundEvent element?
var document = XDocument.Load(path);
var ns = (XNamespace)"urn:abb.com:assetsuite:IF:Event";
var bo = (XNamespace)"urn:abb.com:assetsuite:IF:BO";
var businessobjects =
from elements in document.Element(ns + "OutboundEvent")?.Elements(bo + "BusinessObject")
?? Enumerable.Empty<XElement>()
select elements;

Related

C# XML - Deserializing a list of classes

I'm working with an XML document which is generated using C# from a list of objects (of the 'People' class)
<?xml version="1.0" encoding="utf-8"?>
<ArrayOfDeviceInfo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="DeviceInfoCollection">
<DeviceInfo>
<Partition>0</Partition>
<SerialID>3117132000001</SerialID>
<AzureID>2d680cd1-7320-43a9-87d4-75a2698771a3</AzureID>
<FirmwareVersion>3.0.0</FirmwareVersion>
</DeviceInfo>
<DeviceInfo>
<Partition>0</Partition>
<SerialID>3117132000002</SerialID>
<AzureID>646ca461-9352-4746-9fa6-6308010059fb</AzureID>
<FirmwareVersion>1.1.2</FirmwareVersion>
</DeviceInfo>
My goal is to deserialize this back into a List<DeviceInfo> variable.
I've tried the following
var xDoc = XDocument.Load(Application.StartupPath + "/devicesTEST.xml");
if (File.ReadAllText(Application.StartupPath + "/devicesTEST.xml").Length > 0)
{
var envs = from e in xDoc.Root.Descendants("DeviceInfo")
select new DeviceInfo
{
SerialID = (string)e.Element("SerialID"),
};
Manager.Devices = envs.ToList();
}
and it's working for me on another XML file.
Update
Contrary to previous belief, it turns out there is no error, the list just doesn't get populated with the values extracted from the XML.
XML namespaces; in your xml, the namespace is defined by xmlns="DeviceInfoCollection" - but your code assumes it is the empty (default) namespace. Since xml namespaces are inherited, you need to tell it the namespace throughout:
XNamespace ns = "DeviceInfoCollection";
var devices = from e in xDoc.Root.Descendants(ns + "DeviceInfo")
select new DeviceInfo
{
SerialID = (string)e.Element(ns + "SerialID"),
};
foreach(var device in devices)
{
Console.WriteLine(device.SerialID);
}

c# get values from xml response

I am trying to get values from xml respone :
<?xml version="1.0" encoding="utf-8"?>
<Response xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://adaddaasd.com">
<A>14</A>
<B>Failed</B>
<C>22</C>
</Response>
My code is :
string responseString = await response.Content.ReadAsStringAsync();
var xDocument = XDocument.Parse(responseString);
var responseNode = xDocument.XPathSelectElement("/Response");
var A = xDocument.XPathSelectElement("/Response/A");
But I am getting null values for A and responseNode. Whats wrong? Thanks
You're blatantly ignoring the XML namespace that's defined in your XML document:
<Response xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xmlns:xsd='http://www.w3.org/2001/XMLSchema'
xmlns='http://adaddaasd.com'>
****************************
You need to include that into your querying - I would try to do it like this:
var xDocument = XDocument.Parse(responseString);
// *define* your XML namespace!
XNamespace ns = "http://adaddaasd.com";
// get all the <Response> nodes under the root with that XML namespace
var responseNode = xDocument.Descendants(ns + "Response");
// from the first <Response> node - get the descendant <A> nodes
var A = responseNode.FirstOrDefault()?.Descendants(ns + "A");
If you insist on using the XPathSelectElement method, then you must define an XmlNamespaceManager and use it in your XPath select:
// define your XML namespaces
XmlNamespaceManager xmlnsmgr = new XmlNamespaceManager(new NameTable());
xmlnsmgr.AddNamespace("ns", "http://adaddaasd.com");
// use the defined XML namespace prefix in your XPath select
var A = xDocument.XPathSelectElement("/ns:Response/ns:A", xmlnsmgr);

How to Extract an Element using XPathSelectElement

I am extracting an element from an xml document but it's returning null
<?xml version="1.0" encoding="utf-8"?>
<Test1
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-test"
xmlns="https://www.google.com/partner/testt.xsd">
<Test2>OK</Test2>
<Test3>1439379003</Test3>
</Test1>
I'm trying to extract test2 element but its returning null
var responseXdoc = XDocument.Parse(response);
var statusElement = responseXdoc.XPathSelectElement("/Test1/Test2");
result statusElement as null but I'm expecting Ok
Problem in Namespace
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://www.google.com/partner/testt.xsd (Its my guess)
Your XML has default namespace which elements in the scope inherit implicitly. To reference elements in namespace using XPath, you need to use namespace prefix which, you need to register before in an XmlNamespaceManager :
var nsManager = new XmlNamespaceManager(new NameTable());
nsManager.AddNamespace("d", "https://www.insuranceleads.com/partner/PricePresentationResult.xsd");
var statusElement = responseXdoc.XPathSelectElement("/d:Test1/d:Test2", nsManager);
dotnetfiddle demo
Alternatively, you can use XNamespace and LINQ API to do the same, for example :
XNamespace d = "https://www.insuranceleads.com/partner/PricePresentationResult.xsd";
var statusElement = responseXdoc.Element(d + "Test1").Element(d + "Test2");

Finding a set of nodes in an XML [duplicate]

Can't get any result in feeds.
feedXML has the correct data.
XDocument feedXML = XDocument.Load(#"http://search.twitter.com/search.atom?q=twitter");
var feeds = from entry in feedXML.Descendants("entry")
select new
{
PublicationDate = entry.Element("published").Value,
Title = entry.Element("title").Value
};
What am I missing?
You need to specify the namespace:
// This is the default namespace within the feed, as specified
// xmlns="..."
XNamespace ns = "http://www.w3.org/2005/Atom";
var feeds = from entry in feedXML.Descendants(ns + "entry")
...
Namespace handling is beautifully easy in LINQ to XML compared with everything other XML API I've ever used :)
You need to specify a namespace on both the Descendents and Element methods.
XDocument feedXML = XDocument.Load(#"http://search.twitter.com/search.atom?q=twitter");
XNamespace ns = "http://www.w3.org/2005/Atom";
var feeds = from entry in feedXML.Descendants(ns + "entry")
select new
{
PublicationDate = entry.Element(ns + "published").Value,
Title = entry.Element(ns + "title").Value
};
If you look at the XML returned by the HTTP request, you will see that it has an XML namespace defined:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" ...>
<id>tag:search.twitter.com,2005:search/twitter</id>
...
</feed>
XML is just like C#, if you use an element name with the wrong namespace, it is not considered to be the same element! You need to add the required namepsace to your query:
private static string AtomNamespace = "http://www.w3.org/2005/Atom";
public static XName Entry = XName.Get("entry", AtomNamespace);
public static XName Published = XName.Get("published", AtomNamespace);
public static XName Title = XName.Get("title", AtomNamespace);
var items = doc.Descendants(AtomConst.Entry)
.Select(entryElement => new FeedItemViewModel()
new {
Title = entryElement.Descendants(AtomConst.Title).Single().Value,
...
});
The issue is in feedXML.Descendants("entry"). This is returning 0 results
According to the documentation you need to put in a fully qualified XName

XDocument does not load Xml string properly

I'm trying to do the following: load an Xml string into a XDocument object, but when I try to access elements through Descendants method it return nothing when I tried to see the value of inner elements in Visual Studio it does not recognize it as Xml so what is the problem here?
string xml = #"<ArrayOfKeyValueOfstringint xmlns=""http://schemas.microsoft.com/2003/10/Serialization/Arrays"" xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"">
<KeyValueOfstringint>
<Key>crscmprsn_ttlprt1</Key>
<Value>1</Value>
</KeyValueOfstringint>
<KeyValueOfstringint>
<Key>ptntmntrfrm_ttlprt1</Key>
<Value>1</Value>
</KeyValueOfstringint>
</ArrayOfKeyValueOfstringint>";
var xdoc = XDocument.Parse(xml);
IEnumerable<XElement> elements = xdoc.Descendants("KeyValueOfstringint");
var lst = new List<KeyValuePair<string,int>>();
foreach (var item in elements)
{
var k = item.Element("Key").Value;
int v = int.Parse(item.Element("Value").Value);
var kvp = new KeyValuePair<string,int>(k,v);
lst.Add(kvp);
}
You need to specify namespace to get your elements:
var ns = "http://schemas.microsoft.com/2003/10/Serialization/Arrays";
var elements = xdoc.Descendants(ns + "KeyValueOfstringint");
For more information about xml namespaces take a look at: Working with XML Namespaces

Categories