XmlDoc SelectNodes selecting entire document - c#

I have a simple XML doc with no Namespace
Here is the code I wrote in C# to search for a particular element based on Name.
public XmlElement SearchXML(string name)
{
XmlDocument xDoc = new XmlDocument();
string filePath = ConfigurationManager.AppSettings["path"];
xDoc.Load(filePath);
string xQryStr = "//NewPatient[Name='" + name + "']";
xDoc.SelectNodes(xQryStr);
XmlElement xmlEle = xDoc.DocumentElement;
return xmlEle;
}
The XML document is as follows
When I try to call the method SearchXML and pass Dennis as the arguement, instead of returning the xml element containing only the specific elements, it returns the entire document.
Where am I possibly erring?
Any help appreciated.

xDoc.SelectNodes(xQryStr) does not mutate the original doc. You need to store the return value of this method call and return that instead.
ATM you're simply returning the root element of the original doc (i.e. the entire tree)
EDIT
In answer to your comment, you could fish the first matched XmlElement as follows:
xDoc.SelectNodes(xQryStr).OfType<XmlElement>().FirstOrDefault()
This will return either null or an XmlElement

If you want to select a list of nodes based on an XPath expression, you need to use .SelectNodes in this fashion:
public XmlElement SearchXML(string name)
{
XmlDocument xDoc = new XmlDocument();
string filePath = ConfigurationManager.AppSettings["path"];
xDoc.Load(filePath);
string xQryStr = "//NewPatient[Name='" + name + "']";
XmlNodeList listOfNodes = xDoc.SelectNodes(xQryStr);
foreach(XmlNode node in listOfNodes
{
// do something with that list of XML nodes you've selected....
// XmlElement xmlEle = node;
// return xmlEle;
}
}
The call to .SelectNodes(xpath) returns a list of matching XML nodes (see the MSDN documentation on XmlDocument.SelectNodes) - once you have that list, you can iterate over the matched nodes and do something with them....
Or if you're expecting only a single XML node to match your XPath expression, you can use .SelectSingleNode, too:
string xQryStr = "//NewPatient[Name='" + name + "']";
XmlNode matchedNode = xDoc.SelectSingleNode(xQryStr);
if(matchedNode != null)
{
// do something with that list of XML nodes you've selected....
return matchedNode;
}

can you change
string xQryStr = "//NewPatient[Name='" + name + "']";
to
xQryStr = "/NewPatient[Name='" + name + "']";
see the below link
http://www.csharp-examples.net/xml-nodes-by-name/

Related

XML - Write a single node

I got this function for simply get the inner text of my xml:
XmlDocument document = new XmlDocument();
document.Load("game.xml");
string content = document.SelectSingleNode("Game/Client-Version").InnerText;
(this is the xml file (due to complications with stackoverflow posted on pastebin)): http://pastebin.com/EEeFAJpC
And now I am exactly looking for the function above, just to write. Like
document.WriteSingleNode("Game/Client-Version", "texttowrite");
I did not find anything helping me out.
This should work
XmlElement x = document.SelectSingleNode("Game/Client-Version") as XmlElement;
x.InnerText = "texttowrite";
Create your own extension method:
public void WriteSingleNode(this XmlDocument document, string NodeName, string InnerText)
{
// Create a new element node.
XmlNode newElem = document.CreateNode("element", "pages", "");
newElem.InnerText = InnerText;
Console.WriteLine("Add the new element to the document...");
document.DocumentElement.AppendChild(newElem);
Console.WriteLine("Display the modified XML document...");
Console.WriteLine(document.OuterXml);
}

How can i get xml node value from string

I am trying to get XML values from the following XML node:
<StockQuotes>
<Stock>
<Symbol>LLOY.L</Symbol>
<Last>76.27</Last>
<Date>8/29/2014</Date>
</Stock>
</StockQuotes>
Here is my code:
XmlDocument quoteXML = new XmlDocument();
string strData = myXMLfile;
quoteXML.LoadXml(strData);
XmlNode nodes = quoteXML.SelectSingleNode("StockQuotes/Stock/Last/Date");
string strPrice = nodes["Last"].InnerText;
string strDate = nodes["Date"].InnerText;
Response.Write( strPrice + strDate );
I am getting the error:
Object reference not set to an instance of an object.
when I write the whole string strData to the view I get all of the XML so I know the file is valid.
SOURCE OF THE PROBLEM:
quoteXML.SelectSingleNode("StockQuotes/Stock/Last/Date"); SelectSingleNode call will return representation of <Date>8/29/2014</Date>,
But you try to access subnodes ["Last"] and ["Date"], that are not child nodes of <Date>8/29/2014</Date> and taking into account that indexer returns:
The first XmlElement that matches the specified name. It returns a
null reference (Nothing in Visual Basic) if there is no match.
nodes["Last"] and nodes["Base"] will be both null, resulting in NullReferenceException on .InnerText property access.
SOLUTION:
Use
XmlNode nodes = quoteXML.SelectSingleNode("StockQuotes/Stock");
to access Stock node instead.
The issue was with special charchters in the XML feed. I have resolved the issue and used:
'string strData = WebService.GetDate(); // returns xml as string
string decoded = WebUtility.HtmlDecode(strData); quoteXML.LoadXml(decoded);
XmlDocument xml = new XmlDocument();
xml.LoadXml(decoded);
XmlNodeList xnList = xml.SelectNodes("/StockQuotes/Stock");
foreach (XmlNode xn in xnList)
{
strQuote = xn["Last"].InnerText;
}'

C# code for getting XML element by certain attribute value

I am creating XML document by reading some objects and adding them to proper place (inside xml tree structure). To be able to add it to proper place I need parent XmlNode so I could call parentNode.AppendChild(node);
How can I get XmlNode object if I know value of one of its attributes?
XmlDocument dom = new XmlDocument();
XmlNode parentNode = null;
XmlNode node = dom.CreateElement(item.Title); //item is object that I am writing to xml
XmlAttribute nodeTcmUri = dom.CreateAttribute("tcmUri");
nodeTcmUri.Value = item.Id.ToString();
node.Attributes.Append(nodeTcmUri);
parentNode = ??? - how to get XML node if I know its "tcmUri" attribute value (it is unique value, no other node has same "tcmUri" attribute value)
You can do this using SelectSingleNode function and xpath query as below
XmlNode parentNode = dom.SelectSingleNode("descendant::yournodename[#tcmUri='" + item.Id.ToString() + "']");
Where yournodename has to be replaced with the node name of the parent elements
Try this
XmlDocument doc = new XmlDocument();
doc.LoadXml(content);
XmlNodeList list = doc.SelectNodes("mynode");
foreach (XmlNode item in list)
{
if (item.Attributes["tcmUri"].Value == some_value)
{
// do what you want, item is the element you are looking for
}
}
Use following code:
var nodeList = doc.SelectNodes("<Node Name>[#tcmUri = \"<Value>\"]");
if(list.Count>0)
parentNode = list[0];
Replace <Node Name> with the node name which you want to make the parent node.
Replace the <Value> with the value of tcmUri attribute of the Node which you want to make the parent node.
XPath is your friend :
string xpath = String.Format("//parentTag[#tcmUri='{0}']", "tcmUriValueHere");
//or in case parent node name (parentTag) may varies
//you can use XPath wildcard:
//string xpath = String.Format("//*[#tcmUri='{0}']", "tcmUriValueHere");
parentNode = dom.SelectSingleNode(xpath)

URI to XML parse

I need to convert the URI addres to XML notation.
for example
/Test1/Test2/Test3/
to
<Modul>
<Test1/><Test2/><Test3/>
</Modul>
Here is my code:
private static XmlNode NodeRecurs(XmlNode node, string nodeName)
{
string[] array = nodeName.Split('/');
var xdoc = new XmlDocument();
var name = nodeName.Remove(0, array[0].Length + 1);
XmlNode xmlNode = xdoc.CreateNode(XmlNodeType.Element, array[0], string.Empty);
node.AppendChild(xmlNode);
if (array.Count() != 0)
{
NodeRecurs(node, name);
}
return node;
}
When the NodeRecurs calls itself it is InvalidArgument exeption. It says the it is wrong context for the current node.
To append nodes to a document, they need to be created by the same document.
You are creating a new XmlDocument every time you call the function - create one outside of the function and pass it in as a parameter.

how to read value from XML?

The data:
<sys>
<id>SCPUCLK</id>
<label>CPU Clock</label>
<value>2930</value>
</sys>
<sys>
<id>CPUTEMP</id>
<label>CPU Temp</label>
<value>39</value>
</sys>
This is the code that I'm using to read the data:
XmlDocument document = new XmlDocument();
document.LoadXml(data);
XmlElement node = document.SelectSingleNode("/sys/value") as XmlElement;
Console.WriteLine("node = " + node);
The issue: Console.WriteLine("node = " + node); doesn't give me any output besides node: but no actual value like 2930 from the sample above.
Thanks
use node.value ie., XmlElement.value
As an alternative to using XmlDocument, you can also use LINQ to XML (which is my preference):
using System.Xml.Linq;
XDocument xDoc = new XDocument();
// Parse loads the XDocument with XML from a string
xDoc = XDocument.Parse(data);
string node = (from x in xDoc.Root.Elements("value")
select x.Value).SingleOrDefault();
Console.WriteLine("node = " + node);
Nothing wrong with using XmlDocument, especially for what you're doing, but you might want to check out LINQ to XML when you get a chance, as I find it a lot easier to work with than XmlDocument.
If you want to get all the "value" elements, simply remove the SingleOrDefault() from the query, and then you can loop through the result, like this:
var nodes = from x in xDoc.Root.Elements("value")
select x.Value;
foreach (var node in nodes)
{
Console.WriteLine("node = " + node);
}
Here's a site worth checking out:
LINQ to XML - 5 Minute Overview

Categories

Resources