Select element value with xpath - c#

Given this XML, how to select the value of PostBack using xpath query?
<AuthenticateResponse xmlns="http://example.com/authentication/response/1">
<Status>success</Status>
<Result>more-info</Result>
<StateContext />
<AuthenticationRequirements>
<PostBack>/Authentication/ExplicitForms/AuthenticateAttempt</PostBack>
<CancelPostBack>/Authentication/ExplicitForms/CancelAuthenticate</CancelPostBack>
<CancelButtonText>Cancel</CancelButtonText>
</AuthenticationRequirements>
</AuthenticateResponse>
I would expect this to work but it returns null:
var nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("AuthenticateResponse", "http://example.com/authentication/response/1");
var node = doc.SelectSingleNode("//AuthenticateResponse:AuthenticationRequirements/PostBack", nsmgr);

You should specify namespace for each element you are mentioning in xpath:
var nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ns", "http://example.com/authentication/response/1");
var xpath = "/ns:AuthenticateResponse/ns:AuthenticationRequirements/ns:PostBack";
var node = doc.SelectSingleNode(xpath, nsmgr);

It should be:
var node = doc.SelectSingleNode("/AuthenticateResponse:AuthenticateResponse/AuthenticateResponse:AuthenticationRequirements/AuthenticateResponse:PostBack", nsmgr);

Related

Using underscore and period with XPath

I need to select a node which has attribute name as _1.1.1
I am trying to select the node as
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("IKS", "http://schemas.microsoft.com/wix/2006/objects");
XmlNode xRootNode = xmlDoc.SelectSingleNode("//folder[#name='Global']");
But it doesn't return any. I'm sure its because of the special characters in my expression. How should I handle it to get the desired node?
EDIT: I access node as
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("IKS", "http://schemas.microsoft.com/wix/2006/objects");
XmlNode xRootNode = xmlDoc.SelectSingleNode("//folder[#name='Global']", nsmgr);
and the XML is
<?xml version="1.0" encoding="UTF-8"?>
<workplace xmlns='IKS:'>
<cabinet name='Groups%20and%20Departments' oid='_1.25.18'>
<folder name='Global' oid='_1.11.9882'></folder>
</cabinet>
</workplace>
You're very close to having the correct approach. You have declared a namespace prefix, but you need to actually use it:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("IKS", "http://schemas.microsoft.com/wix/2006/objects");
XmlNode xRootNode = xmlDoc.SelectSingleNode("//IKS:folder[#name='Global']");
// ^^^^------- here
Note: For some reason, you have xmlns="IKS:" in your XML. If that is in fact what your XML looks like, then IKS: is the namespace URI you need to use:
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("IKS", "IKS:");
XmlNode xRootNode = xmlDoc.SelectSingleNode("//IKS:folder[#name='Global']");

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.

Alternatives for System.Xml.Linq to match Xpath

I have used System.Xml.Linq; to match Xpath from xml document. XElement and SaveOptions both get from System.Xml.Linq;.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable());
nsmgr.AddNamespace("ns", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-02-03T16:54:46");
XElement docRfsid = XElement.Parse(content);
//if (docRfsid.XPathSelectElement("//ns:RFSID", nsmgr).Value != null)
if (Regex.Match(docRfsid.ToString(), "RFSID", RegexOptions.IgnoreCase).Success)
{
projData.RfsId = docRfsid.XPathSelectElement("//ns:RFSID", nsmgr).Value.ToString();
}
XElement doc_Financial = XElement.Parse(content);
string resultFinancial = doc_Financial.XPathSelectElement("//ns:Financial", nsmgr).ToString(SaveOptions.DisableFormatting);
I just want to remove System.Xml.Linq; dll since I have to use .net framework 2.0 only.
Is there any other alternatives that I can use to System.Xml.Linq;.
Yes. Use System.Xml.XmlDocument, specifically the SelectNodes() method on it, the DocumentElement property or any XmlElement instance. This method accepts an XPath and returns a list of XmlElements that match (whether they be nodes (XmlNode) or attributes (XmlAttribute)). This is based off the old COM XmlDocument object and is available as far back as version 1.1 of the framework.
System.Xml
Something like
XmlDocument doc = new XmlDocument();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("ns", "http://schemas.microsoft.com/office/infopath/2003/myXSD/2012-02-03T16:54:46");
XmlNode financialNode = doc.DocumentElement.SelectNode("ns:Financial",nsmgr);
strring resultFinancial = null;
if (financialNode != null)
{
resultFinancial = financialNode.InnerText;
}
Sort of thing.

How to Select XML Nodes with XML Namespaces with C#

I have to analyze a XML doc with special namespace using C#, and I get some idea from this post. But my code fail to get the expected XML node, because the XML structure is very special...
There is a namespace in root node in XML
<MDOC xmlns="urn:schemas-microsoft-com/PSS/PSS_Survey01">
Here is my code to get this root node
XmlDocument doc = new XmlDocument();
doc.Load(path);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("urn", "schemas-microsoft-com/PSS/PSS_Survey01");
XmlNode root = doc.SelectSingleNode("MDOC", nsmgr);
Help me!
I am not sure what is special about your XML structure.
I would write the code little differently
string xmlNamespace = String.Empty;
XmlNamespaceManager nsmgr;
XmlNodeList nodeInfo = FABRequestXML.GetElementsByTagName("RootNodeName");
xmlNamespace = Convert.ToString(nodeInfo[0].Attributes["xmlns"].Value);
nsmgr = new XmlNamespaceManager(MyXml.NameTable);
nsmgr.AddNamespace("AB", xmlNamespace);
XmlNode myNode = MyXml.DocumentElement.SelectSingleNode("AB:NodeName", nsmgr);
Hope that helps

Parsing XML in C# from stream

I've tried several methods, from Linq to loading the data to an XML document, but i can't seem to be able to return the result that i need.
here's the example XML:
<serv:message xmlns:serv="http://www.webex.com/schemas/2002/06/service" xmlns:com="http://www.webex.com/schemas/2002/06/common" xmlns:event="http://www.webex.com/schemas/2002/06/service/event"><serv:header><serv:response><serv:result>SUCCESS</serv:result><serv:gsbStatus>PRIMARY</serv:gsbStatus></serv:response></serv:header><serv:body><serv:bodyContent xsi:type="event:createEventResponse" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><event:sessionKey>11111111</event:sessionKey><event:guestToken>111111111111111111111</event:guestToken></serv:bodyContent></serv:body></serv:message>
And, here's what i've tried to do:
StreamReader reader = new StreamReader(dataStream);
XmlDocument doc = new XmlDocument();
doc.LoadXml(reader.ReadToEnd());
XmlNamespaceManager ns = new XmlNamespaceManager(doc.NameTable);
XmlNamespaceManager ns2 = new XmlNamespaceManager(doc.NameTable);
XmlNamespaceManager ns3 = new XmlNamespaceManager(doc.NameTable);
ns.AddNamespace("serv", "http://www.webex.com/schemas/2002/06/service");
ns2.AddNamespace("com", "http://www.webex.com/schemas/2002/06/common");
ns3.AddNamespace("event", "http://www.webex.com/schemas/2002/06/service/event");
XmlNode node = doc.SelectSingleNode("result",ns);
Yet, for some reason i cannot ever seem to return the actual result, which should be either 'SUCCESS' or 'FAILURE' based on the actual xml above.
How can i do this?
your xpath query is not correct.
try this one :
XmlNode node = doc.SelectSingleNode("//serv:result",ns);
or
XmlNode node = doc.SelectSingleNode("serv:message/serv:header/serv:response/serv:result",ns);
This works:
XDocument doc = XDocument.Load(#"test.xml");
XNamespace serv = "http://www.webex.com/schemas/2002/06/service";
var result = doc.Descendants(serv + "result").First().Value;

Categories