Reading Elements within a Namespace - c#

I have an XML file that looks like:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="https://www.someurl.com/somefile.xslt"?>
<AutoInsuranceClaim xmlns="http://www.someurl.com/schemas/AutoInsuranceClaim">
<Identification>
<BaseOwner>3</BaseOwner>
<BaseType>ABC123</BaseType>
<BaseTypeRef>471038341757</BaseTypeRef>
</Identification>
</AutoInsuranceClaim>
and I'm trying to read the Identification node. Here's my code:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"..\..\Data.xml");
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", "http://www.someurl.com/schemas/AutoInsuranceClaim");
XmlNodeList nodeList = xmlDoc.SelectNodes(#"/ns:AutoInsuranceClaim/Identification", nsmgr);
Console.WriteLine("There are {0} nodes...", nodeList.Count);
I know I should get a least 1 value. My understanding of .NET XML parsing is that if you have a default namespace with no prefix, you have to create your own namespace. But this should have returned 1.
If not, what am I missing?

I might be grasping at straws here, but shouldn't you be namespacing both entities in your xpath expression?
XmlNodeList nodeList = xmlDoc.SelectNodes(#"/ns:AutoInsuranceClaim/ns:Identification", nsmgr);

XElement root = XElement.Load("Data.xml");
var identifications = root.Descendants()
.Where(x => x.Name.LocalName == "Identification")
.ToList()

The problem is that you're trying to find an Identification node without a namespace, but it will have defaulted to the same namespace as the parent due to the xmlns=... part. Try this:
var nodeList = xmlDoc.SelectNodes("/ns:AutoInsuranceClaim/ns:Identification",
nsmgr);
Having tried it myself, it printed a count of 1.
Personally I'd use LINQ to XML instead though, which makes namespace easier handling:
XDocument doc = XDocument.Load(#"..\..\Data.xml");
XNamespace ns = "http://www.someurl.com/schemas/AutoInsuranceClaim";
var nodes = doc.Root.Elements(ns + "Identification");

Related

C# how to read single item in node xml

I have xml file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><SENT_110 xmlns:ns2="http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd" xmlns="http://www.mf.gov.pl/SENT/2017/01/18/SENT_110.xsd"><SentNumber>SENT20180416000032</SentNumber><KeyNumber><ns2:SenderKey>KS-28YM</ns2:SenderKey><ns2:RecipientKey>KR-52DH</ns2:RecipientKey><ns2:CarrierKey>KD-48WW</ns2:CarrierKey></KeyNumber>
I want to read in separate SenderKey, RecipientKey & CarrierKey.
When i use this code:
XmlTextReader reader = new XmlTextReader(file);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(reader);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ns", xmlDoc.DocumentElement.NamespaceURI);
XmlNodeList nodeList = xmlDoc.SelectNodes("/ns:SENT_110/ns:KeyNumber", nsmgr);
foreach (XmlNode node in nodeList)
{
key = node.InnerText;
MessageBox.Show(key);
}
i've got something like this: KS-28YMKR-52DHKD-48WW, without any separate between key.
How i could read only one key?
Use the following XPath:
"/ns:SENT_110/ns:KeyNumber/*"
It will return all nested nodes to you.
If the structure of the XML is fixed it is rather easy by using XDocument:
var xmlText = "<SENT_110 xmlns:ns2=\"http://www.mf.gov.pl/SENT/2017/01/18/STypes.xsd\" xmlns=\"http://www.mf.gov.pl/SENT/2017/01/18/SENT_110.xsd\"><SentNumber>SENT20180416000032</SentNumber><KeyNumber><ns2:SenderKey>KS-28YM</ns2:SenderKey><ns2:RecipientKey>KR-52DH</ns2:RecipientKey><ns2:CarrierKey>KD-48WW</ns2:CarrierKey></KeyNumber></SENT_110>";
var xml = XDocument.Parse(xmlText);
var nodes = xml.Descendants();
var senderKey = nodes.First(d => d.Name.ToString().EndsWith("SenderKey")).Value;
var recipientKey = nodes.First(d => d.Name.ToString().EndsWith("RecipientKey")).Value;
var carrierKey = nodes.First(d => d.Name.ToString().EndsWith("CarrierKey")).Value;
See HERE for a working snippet. If this is just a part of a bigger XML or the structure can be different maybe some more complex searching is needed.

SelectNodes Always returning the 0 count

SelectNodes always returning the 0 count even the it has the value.
<?xml version="1.0" encoding="utf-16"?>
<Configurations xmlns="DEH_Common.Schemas">
<sftpConfiguration>
<file>
<filedetails>
<fileext>csv</fileext>
<DataContentDetailId>1</DataContentDetailId>
</filedetails>
</file>
</sftpConfiguration>
</Configurations>
C# to read the nodelist....
XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("//Configurations/sftpConfiguration/file");
It's because of using namespace in your xml, You should add namespace to xmlDoc and also no need to useDocumentElement` This code would be work:
var nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("a", "DEH_Common.Schemas");
XmlNodeList nodeList = xmlDoc.SelectNodes("//a:sftpConfiguration/a:file", nsmgr);
In your XML DocumentElement is the Configurations node, so your XPath should be sftpConfiguration/file
XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("sftpConfiguration/file");
Try this:
xmlDoc.DocumentElement.SelectNodes("/Configurations[#*]/sftpConfiguration/file");

Parsing xml response - Select specific node based on value of another node

I'm new to xml so I'm not sure if I worded the question correctly, but I will do my best to explain.
Basically, I'm trying to parse an xml response in C# such as the one below:
<Premium>
<TotalPremiumAmount>87</TotalPremiumAmount>
<StandardPremium>87</StandardPremium>
<OptionalPremium>0</OptionalPremium>
<StandardTax>0</StandardTax>
<OptionalTax>0</OptionalTax>
<ExtendedTax>0</ExtendedTax>
<ExtendedPremium>0</ExtendedPremium>
<PromotionalPremium>0</PromotionalPremium>
<FeesPremium>0</FeesPremium>
<FeesTax>0</FeesTax>
<StandardFeesPremium>0</StandardFeesPremium>
<OptionalFeesPremium>0</OptionalFeesPremium>
<Tax>0</Tax>
<StandardPremiumDistribution>
<Travelers>
<Traveler>
<TravelerPremium>42</TravelerPremium>
<TravelerTax>0</TravelerTax>
</Traveler>
<Traveler>
<TravelerPremium>45</TravelerPremium>
<TravelerTax>0</TravelerTax>
</Traveler>
</Travelers>
</StandardPremiumDistribution>
<PackagePremiumDistribution>
<Packages>
<Package>
<PackageID>20265</PackageID>
<PackageName />
<PackageTypeID>12</PackageTypeID>
<Premium>87</Premium>
<Fees>0</Fees>
<Tax>0</Tax>
<Travelers>
<Traveler>
<TravelerID>0</TravelerID>
<Premium>42</Premium>
<Tax>0</Tax>
</Traveler>
<Traveler>
<TravelerID>1</TravelerID>
<Premium>45</Premium>
<Tax>0</Tax>
</Traveler>
</Travelers>
</Package>
</Packages>
</PackagePremiumDistribution>
</Premium>
I would like to get the value of the (Traveler) Premium. In the case of only one traveler, I have been using an XMLDocument and the 'SelectSingleNode" function. For example I could do something like:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlResponse);
var premium = xmlDoc.SelectSingleNode("//TravelerPremium").InnerText;
But this wouldn't work when multiple travelers are returned under one plan. For example, I need the premium when TravelerID = 0. How would I go about doing this?
Thanks.
Using XmlDocument:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlResponse);
var premium = xmlDoc.SelectSingleNode("//Premium[../TravelerID = '0']")
You could also iterate through the nodes if multiple could match on this condition like so:
foreach(var premium in xmldoc.SelectNodes("//Premium[../TravelerID = '0']")
{
// do work on each premium node where TravelerID = 0
}
I'd encourage you to look into using LINQ to XML - it's generally easier to work with and will be more performant in most cases. You could even still use XPath expressions, but the following would work:
XDocument xdoc = XDocument.Load(xmlResponse);
var premium = (string)xdoc.Descendants("Traveler").Where(x => (string)x.Element("TravelerID") == "0").Element("Premium");
Assuming your xml looks like that, try something like this:
XmlDocument doc = new XmlDocument();
xmlDoc.Load(xmlResponse);
if (doc.HasChildNodes)
{
foreach (XmlNode node in doc.DocumentElement.ChildNodes)
if (node.Name == "StandardPremiumDistribution")
{
XmlNodeList xnList = node.SelectNodes("//Travelers");
double travelerPremium= xnList.Item(z).FirstChild.InnerText);
}}
Based on this, I think you're gonna do it.
Let's suppose you have a file called XMLFile1.xml with the XML you posted you can iterate through all your TravelerPremium with the following code:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("XMLFile1.xml");
XmlNodeList premiums = xmlDoc.SelectNodes("//TravelerPremium");
foreach(XmlNode node in premiums)
{
MessageBox.Show(node.FirstChild.InnerText);
}
You can also acces the other elements with similar code.

Inserting and removing nodes from an XML namespace

I'm trying to replace a node's name but I'm getting the following error "The reference node is not a child of this node". I think I know why this is happening but can't seem to work around this problem. Here is the XML:
<payload:Query1 xmlns="" xmlns:payload="" xmlns:xsi="" xsi:schemaLocation="">
<payload:QueryId>stuff</payload:QueryId>
<payload:Data>more stuff</payload:Data>
</payload:Query1>
And here is the C# bit:
doc.Load(readStream);
nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("payload", "location");
XmlNode Query1 = doc.SelectSingleNode("//payload:Query1", nsmgr);
public XmlDocument sendReply(args)
{
XmlNode newNode = doc.CreateElement("payload:EditedQuery");
Query.InsertBefore(newNode, Query1);
Query.RemoveChild(Query1);
return doc;
}
I'm trying to replace "Query" with "EditedQuery" but his doesn't work.
If you can use .Net 3.5 LINQ to XML,
XElement root = XElement.Load(readStream);
XNamespace ns = "http://somewhere.com";
XElement Query1 = root.Descendants(ns + "Query1").FirstOrDefault();
// should check for null first on Query1...
Query1.ReplaceWith(new XElement(ns + "EditedQuery"));
Or, if you don't know the namespace, or don't want to hard-code it:
XElement root = XElement.Load(readStream);
XElement Query1 = root.Descendants()
.FirstOrDefault(x => x.Name.Localname == "Query1");
// should check for null first on Query1...
Query1.ReplaceWith(new XElement(Query1.Name.Namespace + "EditedQuery"));
See Jon Skeet's reason why to use LINQ to XML here over older API's.

Read attribute from xml

Can someone help me read attribute ows_AZPersonnummer with asp.net using c# from this xml structure
<listitems
xmlns:s="uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882"
xmlns:dt="uuid:C2F41010-65B3-11d1-A29F-00AA00C14882"
xmlns:rs="urn:schemas-microsoft-com:rowset"
xmlns:z="#RowsetSchema"
xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<rs:data ItemCount="1">
<z:row
ows_AZNamnUppdragsansvarig="Peter"
ows_AZTypAvUtbetalning="Arvode till privatperson"
ows_AZPersonnummer="196202081276"
ows_AZPlusgiro="5456436534"
ows_MetaInfo="1;#"
ows__ModerationStatus="0"
ows__Level="1" ows_ID="1"
ows_owshiddenversion="6"
ows_UniqueId="1;#{11E4AD4C-7931-46D8-80BB-7E482C605990}"
ows_FSObjType="1;#0"
ows_Created="2009-04-15T08:29:32Z"
ows_FileRef="1;#uppdragsavtal/Lists/Uppdragsavtal/1_.000"
/>
</rs:data>
</listitems>
And get value 196202081276.
Open this up in an XmlDocument object, then use the SelectNode function with the following XPath:
//*[local-name() = 'row']/#ows_AZPersonnummer
Basically, this looks for every element named "row", regardless of depth and namespace, and returns the ows_AZPersonnummer attribute of it. Should help avoid any namespace issues you might be having.
The XmlNamespaceManager is your friend:
string xml = "..."; //your xml here
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNamespaceManager nsm = new XmlNamespaceManager(new NameTable());
nsm.AddNamespace("z", "#RowsetSchema");
XmlNode n = doc.DocumentElement
.SelectSingleNode("//#ows_AZPersonnummer", nsm);
Console.WriteLine(n.Value);
You can also use LINQ to XML:
XDocument xd = XDocument.Parse(xml);
XNamespace xns = "#RowsetSchema";
string result1 = xd.Descendants(xns + "row")
.First()
.Attribute("ows_AZPersonnummer")
.Value;
// Or...
string result2 =
(from el in xd.Descendants(xns + "row")
select el).First().Attribute("ows_AZPersonnummer").Value;
I'd say you need an XML parser, which I believe are common. This looks like a simple XML structure, so the handling code shouldn't be too hard.
Use <%# Eval("path to attribute") %> but you need to load the xml has a DataSource.
Otherwise you can load it using XmlTextReader. Here's an example.

Categories