Cannot get XPath to work with unnamed namespace - c#

The XML (fragment):
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<GetXMLResponse xmlns="http://sitecore.net/visual/">
<GetXMLResult>
<sitecore xmlns="">
<status>ok</status>
The code (fragment):
XmlNamespaceManager nsManager = new XmlNamespaceManager(template.NameTable);
nsManager.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
nsManager.PushScope();
XmlNode sitecoreRoot = template.SelectSingleNode("/soap:Envelope/soap:Body/*[namespace-uri()='http://sitecore.net/visual/' and local-name()='GetXMLResponse']", nsManager);
string status = sitecoreRoot.SelectSingleNode("/GetXMLResult/sitecore/status").Value;
sitecoreRoot element returns the correct node. However the XPath to get the status always returns null, even though the siteCoreRoot.OuterXMl property shows the element is present.
The only thing I can think of is the line:
<sitecore xmlns="">
is throwing off the XPath
TIA

XmlNamespaceManager ns = new XmlNamespaceManager(cd.NameTable);
ns.AddNamespace("sp", "http://schemas.xmlsoap.org/soap/envelope/");
ns.AddNamespace("sc", "http://sitecore.net/visual/");
XmlNode sitecoreRoot = cd.SelectSingleNode("//sp:Envelope/sp:Body/sc:GetXMLResponse/sc:GetXMLResult/sitecore/status", ns);
var status = sitecoreRoot.InnerText;
May help you?

If you just want the status node, you can try this xml library and the following XPath.
XElement root = XElement.Load(file); // or .Parse(string)
XElement status = root.XPathElement("//status");
The library handles doing the namespace for you.

Related

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 can I parse the following xml in c#

I need some help on how to get values of English and studentId from this XML. Maybe it needs some special parsing I can't figure out at the moment.
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<processResponse xmlns="http://tempuri.org/">
<processResult>
<xml version="1.0" encoding="UTF-8"?>
<returnedResponse>
<English>94</English>
<Remarks>Excellent</Remarks>
<studentId>tst005</studentId>
<Department>6</Department>
</returnedResponse>
</processResult>
</processResponse>
</soap:Body>
</soap:Envelope>
I have tried the following code:
XmlDocument xdr = new XmlDocument();
xdr.LoadXml(thexml);
XmlNodeList nodelist = xdr.SelectNodes("//processResponse/processResult/returnedResponse");
foreach (XmlNode node in nodelist)
{
string eng = node.SelectSingleNode("English").InnerText;
Response.Write("eng");
}
Do you get an error with invalid XML or does your SelectNodes not find anything?
How about this path
XmlNodeList nodelist = xdr.SelectNodes("/*/*/*/processResponse/processResult/returnedResponse");
You can try with SelectSingleNode, just like this.
var English= xdr.DocumentElement.SelectSingleNode("English").InnerText;
var studentId = xdr.DocumentElement.SelectSingleNode("studentId").InnerText;
1) XML ist invalid at line 6 -> because it does not have a closing tag. If you cannot edit the Service and strip the xml header or encode the resulting xml, you have to strip the line 6 in you consumercode.
2) You have to define the Namespaces!
Btw: I highly recommend using (Linq2XML) XDocument. Your code could look like this:
XDocument xdr = XDocument.Parse(...);
var nodes = xdr.XPathSelectElements("//*[name()='returnedResponse']");
Try this
XmlDocument doc = new XmlDocument();
doc.LoadXml(xmlString);
XmlNodeList nList = doc.GetElementsByTagName("returnedResponse");
foreach (XmlNode node in nList)
{
XElement xelement = XElement.Parse(node.OuterXml);
var Descendents = xelement.Descendants();
foreach (var item in Descendents)
{
//you'll get each of your descendents here
}
}

XPath does not work for selecting in XML

I have an XML document and for the life of me I cannot get data by using XPath. I've tried every sample I could find and no luck. I'm trying to extract the email address. Any thoughts?
The XML:
<?xml version="1.0" encoding="UTF-8"?>
<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:hl7-org:v3" xsi:schemaLocation="urn:hl7-org:v3 CDA.xsd">
<typeId root="test1" extension="test2"/>
<id root="test3" extension="test4"/>
<code code="test5" codeSystem="test6" />
<effectiveTime value="201509171214"/>
<confidentialityCode code="N" codeSystem="test7" codeSystemName="test8" displayName="normal"/>
<languageCode code="en"/>
<recordTarget>
<Role>
<id root="000000" extension="number1"/>
<id root="11111" extension="number2"/>
<addr>
<streetAddressLine>Street</streetAddressLine>
<postalCode>12345</postalCode>
<city>City</city>
<state>STATE</state>
<country>COUNTRY</country>
</addr>
<telecom value="number" use="HP"/>
<telecom value="number" use="MC"/>
<telecom value="email#email"/>
<person>
<name>
<family>family</family>
<given>given</given>
<prefix/>
<suffix/>
</name>
<administrativeGenderCode code="C" codeSystem="code" codeSystemName="code name" displayName="c"/>
<birthTime value="N/A"/>
</person>
</Role>
</recordTarget>
</Document>
To load it:
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml(STRING DATA FROM XML);
XPathNavigator foo = xmlDocument.CreateNavigator();
foo.MoveToFollowing(XPathNodeType.Element);
foo.Select("Document/recordTarget/Role");
I've also tried:
XmlNodeList xmlNodeList = xmlDocument.SelectNodes("/Document/recordTarget/Role");
But none of this works. Everything comes back empty. Any ideas? I can't seem to navigate past the root.
I've also tried adding the namespace manager in the selects, with no luck.
XmlNamespaceManager manager = new XmlNamespaceManager(xmlDocument.NameTable);
You must add a namespace
XPathNavigator navigator = xmlDocument.CreateNavigator();
XmlNamespaceManager manager = new XmlNamespaceManager(navigator.NameTable);
manager.AddNamespace("ns", "urn:hl7-org:v3");
var role = navigator.Select("/ns:Document/ns:recordTarget/ns:Role", manager);
Try this:
//Create a namespacemanager to get the defaultnamespace of the xml document
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDocument.NameTable);
//XPath to find the tag that the value isn't equals to number, in this case, it will
//return the <telecom value="email#email"/> element
String xpathQuery = "//role//telecom[#value!='number']";
If you are going to use XPath to get some attribute value, after the XPathNavigator foo = xmlDocument.CreateNavigator(); you should
use the SelectSingleNode method:
//from the XPathNavigator object, we call the SelectSingleNode method, to select a single
//node using the specified xpath query and then call the GetAttribute method to finally
//get the value attribute from that element
String email = foo.SelectSingleNode(xpathQuery).GetAttribute"value",nsmgr.DefaultNamespace);

How to get the Element value from returned Soap based XML Message

I am to get the element value of Soap based retuned XML as below.
XML File:
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<SendToDSSResponse xmlns="http://tempuri.org/">
<SendToDSSResult>
<RC>0</RC>
<RCD></RCD>
<PCKT>
<IDNO>1212</IDNO>
<IDTYPE>051</IDTYPE>
<NOBOX>121216</NOBOX>
<NAME>James</NAME>
</PCKT>
</SendToDSSResult>
</SendToDSSResponse>
</soap:Body>
</soap:Envelope>
Now I want to get the values of IDNO, NoBox and Name. I am trying to use the following code below to get the values but it throws an Exception. What's the correct way to get the element values?
C# Code:
var xDoc = XDocument.Parse(cleanXml); //OR XDocument.Load(filename)
string Name = xDoc.Descendants("Name").First().Value;
I think you should add XNamespace and then you can read out the specific value from the nodes or tags under the node, try this demo in your ConsoleApplication:
XDocument doc = XDocument.Load("XMLFile1.xml");
var result = doc.Descendants(XNamespace.Get("http://tempuri.org/")+"NAME").First();
Console.WriteLine(result.Value);
Use Root property.
string name = xDoc.Root.Descendants("NAME").First().Value;

how we can set value for xml element using XmlDocument class

Is it possible to set value dynamically for any XML element using the XmlDocument class? Suppose my XML is
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
<soapenv:Body>
<v9:ProcessShipmentReply xmlns:v9="http://fedex.com/ws/ship/v9">
<v9:HighestSeverity xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">SUCCESS</v9:HighestSeverity>
<v9:Notifications xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<v9:Severity>SUCCESS</v9:Severity>
<v9:Source>ship</v9:Source>
<v9:Code>0000</v9:Code>
<v9:Message>Success</v9:Message>
<v9:LocalizedMessage>Success</v9:LocalizedMessage>
</v9:Notifications>
<v9:CompletedShipmentDetail>
<v9:CompletedPackageDetails xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<v9:SequenceNumber>1</v9:SequenceNumber>
<v9:TrackingIds>
<v9:TrackingIdType>GROUND</v9:TrackingIdType>
<v9:TrackingNumber>634649515000016</v9:TrackingNumber>
</v9:TrackingIds>
<v9:Barcodes>
<v9:BinaryBarcodes>
<v9:Type>COMMON_2D</v9:Type>
<v9:Value>Wyk+HjAxHTAyMDI3ODAdODQwHTEzNx02MzQ2NDk1</v9:Value>
</v9:BinaryBarcodes>
<v9:StringBarcodes>
<v9:Type>GROUND</v9:Type>
<v9:Value>9612137634649515000016</v9:Value>
</v9:StringBarcodes>
</v9:Barcodes>
<v9:Label>
<v9:Type>OUTBOUND_LABEL</v9:Type>
<v9:ShippingDocumentDisposition>RETURNED</v9:ShippingDocumentDisposition>
<v9:Resolution>200</v9:Resolution>
<v9:CopiesToPrint>1</v9:CopiesToPrint>
<v9:Parts>
<v9:DocumentPartSequenceNumber>1</v9:DocumentPartSequenceNumber>
<v9:Image>iVBORw0KGgoAAAANSUhEUgAAAyAAAASwAQAAAAAryhMIAAAagEl</v9:Image>
</v9:Parts>
</v9:Label>
</v9:CompletedPackageDetails>
</v9:CompletedShipmentDetail>
</v9:ProcessShipmentReply>
</soapenv:Body>
How could I set value for the below element like
<v9:Severity>SUCCESS</v9:Severity>
<v9:Source>ship</v9:Source>
I know how to extract data from XML and I think it is also possible to set value for the XML element using XMLDocument class. Looking for guidance.
If you know how to select a value, then you probably know how to update one too.
XmlDocument doc = new XmlDocument();
doc.Load(...);
XmlNamespaceManager nsMgr = new XmlNamespaceManager(doc.NameTable);
nsMgr.AddNamespace("v9", "http://fedex.com/ws/ship/v9");
XmlNode severityNode = doc.SelectSingleNode("//v9:Severity", nsMgr);
severityNode.innerText = "FAILURE";
The important thing to know is that the <v9:Severity> node has an inner text() node, so in the example above you can't use the Node.Value property. To do that you would do something like this instead:
XmlNode severityTextNode = doc.SelectSingleNode("//v9:Severity/text()", nsMgr);
severityTextNode.Value = "FAILURE";
Note the subtle differences.
Do an XPath to the superior node using the XMLDocument class and add the 2 extra nodes on the tree.

Categories