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);
}
}
Related
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.
I want to read particular node in XML like if any "Log"(root node) node contain "Message" node the it should read all the node under the "Log" node.
Note : Log node is root node and there are many node under "log" node.
for Example :
<TestLogDataSet>
<Log>
<Assembly>TestCase</Assembly>
<TestMethod>Application</TestMethod>
<Status>Passed</Status>
<Trace />
</Log>
<Log>
<Assembly>TestCase</Assembly>
<TestMethod>Application</TestMethod>
<Status>Failed</Status>
<Message>
<pre><![CDATA[ Error while deleting the Project]]>
</pre>
</Message>
<Trace />
</Log>
</TestLogDataSet>
Code :
string xmlFile = File.ReadAllText(#"D:\demo.xml");
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlFile);
foreach (XmlNode lognode in xmlDoc.SelectNodes("/TestLogDataSet/Log[Message]"))
{
foreach (XmlNode node in lognode.ChildNodes)
{
string n1 = node.InnerText;
textBox1.Text = n1 + "\r\n";
}
}
You can use XPath for this.
StringBuilder nodeText = new StringBuilder();
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(<your xml here>);
foreach (XmlNode lognode in xmlDoc.SelectNodes("/TestLogDataSet/Log[Message]")) //select all log nodes with Message as child tag
{
string status = lognode.SelectSingleNode("./Status").InnerText;
if (!string.Equals(status,"failed",StringComparison.OrdinalIgnoreCase))
{
continue;
}
foreach (XmlNode node in lognode.ChildNodes)
{
nodeText.Append(node.LocalName);
nodeText.Append(":");
nodeText.Append(node.InnerText);//read inner text of node here
nodeText.Append("\n");
}
}
Console.WriteLine(nodeText.ToString());
If you want the Log nodes then this should suffice:
var nodes =
xd
.Root
.Elements("Log")
.Where(x => x.Element("Message") != null);
That gives:
If you want a list of all of the child nodes (which is what I understand you want from your question, but it seems a bit odd) then this works:
var nodes =
xd
.Root
.Elements("Log")
.Where(x => x.Element("Message") != null)
.SelectMany(x => x.Elements());
This gives:
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
}
My xml file:
<?xml version="1.0" encoding="utf-8"?>
<layout name="layout">
<section name="Header">
<placeholder name="headers" width="30" class="header">sam,pam</placeholder>
</section>
<section name="Content">
<placeholder name="RightA" width="55">location</placeholder>
</section>
</layout>
I want to replace whole node if its contain sam.Means if node contains sam I want to rewrite node:
<placeholder name="headers" width="4,5,91">sam,sam2,pam</placeholder>
instead of:
<placeholder name="headers" width="30" class="header">sam,pam</placeholder>
In c#:
XmlDocument doc = new XmlDocument();
string sFileName = #"FileNameWithPath";
doc.Load(sFileName );
foreach (XmlNode ....... )
{
//Need help hear how to loop and replace.
}
Thanks.
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load("Path");
XmlNodeList nodeList = xmlDoc.SelectNodes("section") ;
foreach (XmlNode node in nodeList)
{
XmlNode childNode = node.SelectSingleNode("placeholder");
if (childNode.Value.Contains("sam"))
{
childNode.Value = "sam,pam,sam2";
childNode.Attributes["width"].Value = "4,5,91";
}
}
xmlDoc.Save("Path");
Try using an XDocument for better control over find and replace.
XDocument myDocument = XDocument.Load("path to my file");
foreach (XElement node in myDocument.Root.Descendants("placeholder"))
{
if (node.Value.Contains("same"))
{
XElement newNode = new XElement("placeholder");
newNode.Add(new XAttribute("header", node.Attribute("header").Value); // if you want to copy the current value
newNode.Add(new XAttribute("width", "some new value"));
node.ReplaceWith(newNode);
}
}
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);
}