Select XMLNode with XPath - c#

I have seen multiple post with this example but for some reason all options I try return an empty XmlNodeList. What am I missing?
My XML:
<string xmlns='http://ws.jobboard.com/resumes/'>
<Packet>
<Errors />
<PageNumber>1</PageNumber>
<SearchTime>02/25/2014 10:11:47</SearchTime>
<FirstRec>1</FirstRec>
<LastRec>100</LastRec>
<Hits>206816</Hits>
<MaxPage>40</MaxPage>
<Results>
<ResumeResultItem_V3>
<ContactEmail></ContactEmail>
<ContactName>Lisa Yada</ContactName>
<HomeLocation>US-CO-Lakewood</HomeLocation>
<LastUpdate>2014/2/24</LastUpdate>
<ResumeTitle>Web Design & Developement</ResumeTitle>
<JobTitle>Web Design & Developement</JobTitle>
<RecentEmployer>Some Company</RecentEmployer>
<RecentJobTitle>Web Design</RecentJobTitle>
<RecentPay>0</RecentPay>
<ResumeID>RHV47X78Z5CN56</ResumeID>
<UserDID>UHT6R86LL8C581</UserDID>
<ContactEmailMD5>93ce261b843f58962f9</ContactEmailMD5>
<ActionType />
<HighestDegree>Bachelor's Degree</HighestDegree>
<MonthsOfExperience>40</MonthsOfExperience>
<LastActivity>2/24/2014 1:22:19 PM</LastActivity>
</ResumeResultItem_V3> ...
and my code:
XmlDocument jobsdoc = new XmlDocument();
jobsdoc.LoadXml(xmlstring);
XmlNodeList xnList = jobsdoc.SelectNodes("/string/Packet/Results/ResumeResultItem_V3");
foreach (XmlNode xn in xnList)
{
DataRow dr = table.NewRow();
dr["ContactName"] = xn["ContactName"].InnerText;
dr["ResumeTitle"] = xn["ResumeTitle"].InnerText;
...
table.Rows.Add(dr);
}
return table;
I have tried many variations of "/string/Packet/Results/ResumeResultItem_V3" to no avail. The ws is a third party so I have no control over the format of the XML. Thanx in advance.

You need a namespacemanager in your SelectNodes call because your xml root node has a namespace http://ws.jobboard.com/resumes/
Notice that your XPath needs to explicitely use the namespace-alias.
NameTable nt = new NameTable();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
nsmgr.AddNamespace("r", "http://ws.jobboard.com/resumes/");
XmlDocument jobsdoc = new XmlDocument(nt);
jobsdoc.LoadXml(xmlstring);
var xnList = jobsdoc.SelectNodes(
"/r:string/r:Packet/r:Results/r:ResumeResultItem_V3",
nsmgr);
foreach (XmlNode xn in xnList)
{
// rest of your code
}

Related

C# - Unable to get node value from xml file

I'm trying to get the inner text from a node after loading the XML file.
I have tried this code with another file and it worked. But here I can't get the node values.
Can anyone point out what am I doing wrong?
XML file - restaurant_reviews.xml
<?xml version="1.0"?>
<restaurants xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.algonquincollege.com/onlineservice/reviews">
<restaurant>
<name>Laughing Man</name>
<logo>
<name>Visit the Laughing Man</name>
<imagefile>laughing-man.gif</imagefile>
<width unit="px">50</width>
<height unit="px">200</height>
</logo>
</restaurant>
<restaurant>
<name>Gong’s Asian Cuisine</name>
<logo>
<name/>
<imagefile>gong-asian-cuisine.gif</imagefile>
<width unit="px">150</width>
<height unit="px">250</height>
</logo>
</restaurant>
</restaurants>
C# Code
List<string> names = new List<string>();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(HttpContext.Current.Server.MapPath(#"~/App_Data/restaurant_reviews.xml"));
XmlNodeList nodes = xmlDoc.SelectNodes("/restaurants/restaurant");
foreach (XmlNode itemNode in nodes)
{
XmlNode titleNode = itemNode.SelectSingleNode("name");
if (titleNode != null)
{
names.Add(titleNode.InnerText);
}
}
Whilst this question already has an accepted answer, I wanted to add this anyway, as removing namespaces and manipulating XML in this way doesn't feel right to me, it was added for a reason I suspect.
What I believe is the correct approach is too add an XML Namespace Manager to your XPath query.
var nsMgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsMgr.AddNamespace("r", "http://www.algonquincollege.com/onlineservice/reviews");
Then in your SelectNodes and SelectSingleNodes, you add the namespace to the query and pass in the manager, like so.
XmlNodeList nodes = xmlDoc.SelectNodes("/r:restaurants/r:restaurant", nsMgr);
and
XmlNode titleNode = itemNode.SelectSingleNode("r:name", nsMgr);
But if you're happy with the other solution and can manipulate it in this way then go for it I guess.
If you remove this xmlns="http://www.algonquincollege.com/onlineservice/reviews" in your xml it works. I don't know why but the xmlDoc.SelectNodes("/restaurants/restaurant"); do not find any nodes with this xmlns namespace.
This is the code I worked with and it works:
string xml = #"<?xml version=""1.0""?>
<restaurants xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
<restaurant>
<name>Laughing Man</name>
<logo>
<name>Visit the Laughing Man</name>
<imagefile>laughing-man.gif</imagefile>
<width unit=""px"">50</width>
<height unit=""px"">200</height>
</logo>
</restaurant>
<restaurant>
<name>Gong’s Asian Cuisine</name>
<logo>
<name/>
<imagefile>gong-asian-cuisine.gif</imagefile>
<width unit=""px"">150</width>
<height unit=""px"">250</height>
</logo>
</restaurant>
</restaurants>";
List<string> names = new List<string>();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xml);
XmlNodeList nodes = xmlDoc.SelectNodes("/restaurants/restaurant");
foreach (XmlNode itemNode in nodes)
{
XmlNode titleNode = itemNode.SelectSingleNode("name");
if (titleNode != null)
{
names.Add(titleNode.InnerText);
}
}
The problem was with namespace. Thanks to #Sean in the comment section I have resolved the issue. Thanks to #Presi also for pointing out the namespace attribute was the problem.
List<string> names = new List<string>();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(HttpContext.Current.Server.MapPath(#"~/App_Data/restaurant_reviews.xml"));
var namespaceName = "ns";
var namespacePrefix = string.Empty;
XmlNamespaceManager nameSpaceManager = null;
if (xmlDoc.LastChild.Attributes != null)
{
var xmlns = xmlDoc.LastChild.Attributes["xmlns"];
if (xmlns != null)
{
nameSpaceManager = new XmlNamespaceManager(xmlDoc.NameTable);
nameSpaceManager.AddNamespace(namespaceName, xmlns.Value);
namespacePrefix = namespaceName + ":";
}
}
XmlNodeList nodes = xmlDoc.SelectNodes(string.Format("/{0}restaurants/{0}restaurant", namespacePrefix), nameSpaceManager);
foreach (XmlNode itemNode in nodes)
{
XmlNode titleNode = itemNode.SelectSingleNode(namespacePrefix + "name", nameSpaceManager);
if (titleNode != null)
{
names.Add(titleNode.InnerText);
}
}

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.

Iterate through XmlElement's Children (SelectSingleNode returning NULL)

I am trying to loop through an XML element and assign the values to member variables of an object. Below is what I have tried. however SelectSingleNode() is returning NULL. data.Any is a XmlElement array (returned by a service). I have tried using a XmlNamespaceManager, but data.Any is not a XmlDocument so it does not contain a NameTable. What am I doing wrong?
CODE:
foreach (XmlElement item in data.Any)
{
result.CorrelationID = item.SelectSingleNode("CorrelationID").InnerText;
}
XML:
<CorrelationID xmlns="http://www.host.com/folder/anotherFolder">9B36D7A7EDD26A22</CorrelationID>
<EmployerRef xmlns="http://www.host.com/folder/anotherFolder">1235/AN612</EmployerRef>
<Name xmlns="http://www.host.com/folder/anotherFolder">
<Ttl>MS</Ttl>
<Fore>NameFirst</Fore>
<Sur>NameLast</Sur>
</Name>
<PayId xmlns="http://www.host.com/folder/anotherFolder">FLDA/12</PayId>
<NINOToUse xmlns="http://www.host.com/folder/anotherFolder">SL3747A</NINOToUse>
<MessageID xmlns="http://www.host.com/folder/anotherFolder">3</MessageID>
foreach (XmlElement item in data.Any)
{
XmlDocument doc = item.OwnerDocument;
XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("af", "http://www.host.com/folder/anotherFolder");
result.CorrelationID = item.SelectSingleNode("af::CorrelationID", nsmgr).InnerText;
}

How to get element value using c#

XML file:
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<content>
<FingerPrintUserDetails>
<UserID>e57645</UserID>
<UserName>Jill</UserName>
<FPData>AQAAABQAAAD0AAAAAQASAAEAWgAAAAAA8AAAAHfrWpB6BHZBL10voxpdxu2Km5XVNh*oUNC80Rvpql3RhlqOiBPeet6iRPwb/BdN1fCF4Y/WHbQ40*mqoUKqilgN7bUqNuXP7M299HUWtoAGEO3nDKXXAnHd7dgytZbmHVv*mRBPJDSRw9VY/R1yOIu2cCDlLM*F8Q1lvTfMFDdfwNZynI0e2ZauCF58f0UX56XLFBallaAauxP5mvvhUmcmc6ITg7RhH9wc4181kgPjCuZg38pQepE5U07XIa3hQP8fwxPzdprifXECgB1Z3pTXWQP0q4ZD0Inlbq6Gszo1ucPrhQA0jYQRXtJUVuyBeg</FPData>
<Address>Pune</Address>
<ContactNo>848488484884</ContactNo>
</FingerPrintUserDetails>
<FingerPrintUserDetails>
<UserID>444</UserID>
<UserName>John</UserName>
<FPData>AQAAABQAAADkAAAAAQASAAEAZAAAAAAA4AAAAPLnmQ8FymAAHWYutR5pdtYvfDVmjsqLeli8tOSTFAtw6AkfA0r8XwrMzp9jFZJI7DlBk4G94BMq55gPEG7uBLZUNYrvhv0jDlDFMOjWGJ9RoWekFveTC*oZ7Tq/xmxuvY6FzLHVo*xzdKQI73Y0f9/eeMC0OgqnbQ3I0IP6cTkkKnTUZJOXKr7IFPHkjJAvCDmU7ec4vG50JHdBJIObmbzVcO0huTUQyE7CR1qYkUjmNFKgVKWPLRupEk4l/Ek0BuAba*9JlhBVUHzZuKbDQLc9lTFwevAgDuuAwxfZaLS*</FPData>
<Address>nagpur</Address>
<ContactNo>464645763</ContactNo>
</FingerPrintUserDetails>
<FingerPrintUserDetails>
<UserID>5555</UserID>
<UserName>Jack</UserName>
<FPData>AQAAABQAAAAEAQAAAQASAAEAZAAAAAAA9AAAAPz5mQO3uTeXLfU5Mb74XbCX5rERGZFPQMVG1vPpX87306O5oURlYiIe5dasJ2S8NlBZu2UU3zaUpNnB7viYDB6*wfFlgtopn/WdbXW0Yhik3hj8nDreEmaK12To8qfAJx2ooq43i0wBIL*0Jkba*QpHIprSajrhnCg1PjOLMP37sEauJUwXJaoDR/PPQYIxTFE5kf8xzGlJmqiGejD*Y8R3ewU9yIrxkdQ0S//LCdacULt2QvS/I3APo/j0FAgSCOU3SBLdDL6UBPD4fLeEzo7uUIW8gUMThzZX*u2iUuNwJdqWC2NsFtWkUWt03sz3xYQpR8pLA4vrsUmldzUMWe8</FPData>
<Address>beed</Address>
<ContactNo>5745745747</ContactNo>
</FingerPrintUserDetails>
</content>
C#:
XmlDocument doc = new XmlDocument();
doc.Load("E://BioEnable_Project//fp_project_using_xml//fp_project_using_xml//Capture_Data.xml");
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("FPData");
foreach(XmlElement node in nodes)
{
MessageBox.Show(node.Value);
}
I have to check FPData value on each node..i use above code but not getting..
In your XPath, provide the full path to the node.
XmlNodeList nodes = root.SelectNodes("/content/FingerPrintUserDetails/FPData");
What is happening is that there is no direct FPData node under the document root.
XmlNodeList nodes = root.SelectNodes("content/FingerPrintUserDetails");
it will return array of FingerPrintUserDetails, then find FPData in them
XmlNodeList res = nodes[index].SelectNodes("FPData");
Using LINQ to XML:
XDocument doc = XDocument.Load("XmlFilePath");
var selectors = from elements in doc.Elements("content").Elements("FingerPrintUserDetails")
select elements;
foreach (var element in selectors)
{
MessageBox.Show(element.Element("FPData").Value);
}
XmlDocument doc = new XmlDocument();
doc.Load("E://BioEnable_Project//fp_project_using_xml//fp_project_using_xml//Capture_Data.xml");
XmlNodeList lst = doc.GetElementsByTagName("FingerPrintUserDetails");
foreach (XmlElement elem in lst)
{
XmlNode pfData = doc.GetElementsByTagName("FPData")[0];
MessageBox.Show(pfData.Value);
}

Wrap XmlNode with tags - C#

I have the following xml:
<span>sometext</span>
and I want to wrap this XmlNode with another tag:
<p><span>sometext</span></p>
How can i achieve this. For parsing i use XmlDocument (C#).
The above "best answer" works if you don't care that the new "p" node ends up at the end of the parent. To replace it where it is, use:
string xml = "<span>sometext</span>";
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(xml);
// If you have XmlNode already, you can start from this point
XmlNode node = xDoc.DocumentElement;
XmlElement clone = node.Clone();
XmlNode parent = node.ParentNode;
XmlElement xElement = xDoc.CreateElement("p");
xElement.AppendChild(clone);
parent.ReplaceChild(xElement, node);
you can try something like this.
string xml = "<span>sometext</span>";
XmlDocument xDoc = new XmlDocument();
xDoc.LoadXml(xml);
// If you have XmlNode already, you can start from this point
XmlNode node = xDoc.DocumentElement;
XmlNode parent = node.ParentNode;
XmlElement xElement = xDoc.CreateElement("p");
parent.RemoveChild(node);
xElement.AppendChild(node);
parent.AppendChild(xElement);
You must use the CreateNode(XmlNodeType.Element, "p", "") of XmlDocument.
Then append the old node to the new one with the AppendChild method

Categories