how to extract particular attribute from xml file using c#? - c#

static void Main(string[] args)
{
WebClient _httpReq = new WebClient(); // to talk to the web only for get method
string response = _httpReq.DownloadString("https://open-ic.epic.com/FHIR/api/FHIR/DSTU2/Patient?family=Argonaut&given=Jason");
Console.WriteLine(response);\\prints the xml string fetched from FHIR provider EPIC
XmlDocument xml = new XmlDocument();
xml.LoadXml(response); // suppose that myXmlString contains "<Names>...</Names>"
XmlNodeList xnList = xml.SelectNodes("/entry/resource/patient/name");
// here code is trying to extract the name attribute
foreach (XmlNode xn in xnList)
{
string firstName = xn["family value"].InnerText;
string lastName = xn["given value"].InnerText;
Console.WriteLine("Name: {0} {1}", firstName, lastName);
//print the first name and last name of the patient
}
Console.ReadLine();
}

i do it like this:
XmlDocument MyDocument = new XmlDocument();
MyDocument.Load("...");
XmlNode MyNode = MyDocument.SelectSingleNode("/Node_Name");
foreach (XmlAttribute MyAttribute in MyNode.Attributes)
{
if (MyAttribute.Name == "Attribute_Name")
{
object Value = MyAttribute.Value;
break;
}
}

Review XPath. Once you start understanding it, you will find it efficient and easier to code than iterating through lists. It also lets you directly get the nodes/attributes you want.
Then the code would be something similar to
string attrVal = doc.SelectSingleNode("/entry/resource/patient/#name").Value;
Or you can Load XML in XMlDocument and You can fetch element and out of that element you can read specific atairbute,
XmlDocument doc = new XmlDocument();
doc.LoadXml("<reply success=\"true\">More nodes go here</reply>");
XmlElement root = doc.DocumentElement;
string s = root.Attributes["success"].Value;

Related

XML element not displaying for empty values

I am using an xml file to import into the database using the below code
CS:
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(pathPMO + "Data.xml");
XmlNodeList nodeList = xmlDoc.DocumentElement.SelectNodes("/DocumentElement/Profile");
bool insertProfile = false;
foreach (XmlNode node in nodeList)
{
strYear = node.SelectSingleNode("Profile_x0020_Year").InnerText;
strID = node.SelectSingleNode("Profile_x0020_ID").InnerText;
strLead = node.SelectSingleNode("Profile_x0020_Leader").InnerText;
insertProfile = ImportProfile(strYear, strID, strLead);
}
For instance the profile leader values are empty for certain rows and when I try to insert them I get an error object not set to an instance of an object because of that particular element missing in few rows.
Can anyone suggest how to solve this?
You should ensure that each XmlNode object is not null. You can use a simple method like that:
private string GetXmlNodeString(string nodeName, XmlNode node)
{
if(String.IsNullOrWhiteSpace(nodeName))
return String.Empty;
var singleNode = node.SelectSingleNode(nodeName);
if(singleNode ==null)
return String.Empty;
return singleNode.InnerText;
}
then change your code like that:
foreach (XmlNode node in nodeList)
{
strYear = GetXmlNodeString("Profile_x0020_Year",node);
strID = GetXmlNodeString("Profile_x0020_ID",node);
strLead = GetXmlNodeString("Profile_x0020_Leader",node);
insertProfile = ImportProfile(strYear, strID, strLead);
}

Can't get attribute value with C# XPath

I've spent so much time with this already, still can't get the value of NTE attribute. Can someone please help?
C#
StreamReader sr = new StreamReader(resp.GetResponseStream());
XPathDocument xmlDoc = new XPathDocument(sr); // holds xml document
XPathNavigator xmlNav = xmlDoc.CreateNavigator(); //evaluates XPath expressions
XPathNodeIterator node = xmlNav.Select("/DATA2SC/CALL");
string dne = xmlNav.GetAttribute("NTE", "");
Console.WriteLine(dne);
sr.Close();
XML
<?xml version="1.0"?>
<DATA2SC PIN="00000">
<CALL
TR_NUM="00000001"
STATUS="WAITING_FOR_APPROVAL"
NTE="$15.00">
<PROBLEM>
Text
</PROBLEM>
</CALL>
</DATA2SC>
Can you try this code please ?
I already check and it's work
StreamReader sr = new StreamReader("c:\\x.xml");
XPathDocument xmlDoc = new XPathDocument(sr); // holds xml document
XPathNavigator xmlNav = xmlDoc.CreateNavigator(); //evaluates XPath expressions
var node = xmlNav.SelectSingleNode("/DATA2SC/CALL");
string dne = node.GetAttribute("NTE", "");
Console.WriteLine(dne);
OR
XDocument docXmlWorld = XDocument.Load("c:\\x.xml");
foreach (var node1 in docXmlWorld.Descendants("DATA2SC"))
{
foreach (var node2 in node1.Descendants("CALL"))
{
string dne = node2.Attribute("NTE").Value;
Console.Out.WriteLine(dne);
}
}
Or you can do like this too:
XDocument docXmlWorld = XDocument.Load("c:\\x.xml");
//Get the first child => [DATA2SC]
XElement elementNodeDATA2SC = docXmlWorld.Element("DATA2SC");
//Get the first child => [CALL]
XElement elementNodeCALL = elementNodeDATA2SC.Element("CALL");
//Get the attribute NTE from [CALL] node
string dne = elementNodeCALL.Attribute("NTE").Value;
Console.Out.WriteLine(dne);
The Select method, returns a collection of all nodes with the specified XPath.
You can use SelectSingleNode, to select the first node.
var node = xmlNav.SelectSingleNode("/DATA2SC/CALL");
string dne = node.GetAttribute("NTE", "");

how to get the value from innerXMl correctly

I plan to retrieve each suggestion in array and then stroe it in to the list. I have trouble retrieve the option node data, in this pattern {aeroplane,aeroplanes, aerobian} {i}, Any kind soul can help me out with it.
XmlDocument findStringDoc = new XmlDocument();
findStringDoc.Load (Application.dataPath+ "/" + filename);
XmlNodeList nodeList = findStringDoc.SelectNodes("/results/error");
//XmlNodeList suggestionNodeList = findStringDoc.SelectNodes("/results/error/suggestions/option");
foreach(XmlNode xn in nodeList){
errorString.Add(xn["string"].InnerText);
errorType.Add(xn["type"].InnerText);
//string temp = xn["suggestion"].InnerXml;
////TODO: Retrieve suggestions here!
XmlNodeList suggestionNodeList = findStringDoc.SelectNodes("/suggestions");
foreach(XmlNode yn in suggestionNodeList){
option[suggestionNodeList.Count] = yn["option"].InnerText;
Debug.Log(yn["option"].InnerText);
}
suggestionResult.Add (option);
//Debug.Log(suggestionResult);
//XmlNodeList suggestionNodeList = findStringDoc.SelectNodes("/results/error[string='{0}']/suggestions/option",errorString[i]);
}
<results>
<error>
<string>aeroplan</string>
<description>Spelling</description>
<precontext>a</precontext>
<suggestions>
<option>aeroplane</option>
<option>aeroplanes</option>
<option>aerobian</option>
</suggestions>
<type>spelling</type>
</error>
<error>
<string>i</string>
<description>Make I uppercase</description>
<precontext></precontext>
<suggestions>
<option>I</option>
</suggestions>
<type>grammar</type>
<url>http://service.afterthedeadline.com/info.slp?text=i&tags=PRP&engine=1</url>
</error>
</results>
You can use my code below:
private static void GetSuggestionOption(string filename, string value, string optionSuggest)
{
XDocument xDoc = XDocument.Parse(filename);
var parentNode = xDoc.Descendants().Where(x => x.Value == value).Ancestors().FirstOrDefault();
var childNode = parentNode.Descendants().Where(x => x.Name == optionSuggest);
childNode.ToList().ForEach(x => Console.WriteLine(x.Value));
}
Calling: GetSuggestionOption(fileName, "aeroplan", "option");
Happy Coding!
You can use XmlDocument.SelectNodes() method passing suitable XPath string parameter to select specific element(s) from XmlDocument, for example :
public void GetSuggestionOption(string keyword)
{
XmlDocument doc = new XmlDocument();
doc.Load (Application.dataPath+ "/" + filename);
string xpath = string.Format("//error[string='{0}']/suggestions/option", keyword);
XmlNodeList optionSuggestionList = doc.SelectNodes(xpath);
foreach (XmlNode option in optionSuggestionList)
{
Debug.Log(option.InnerXml);
}
}
You can call the method this way for example : GetSuggestionOption("aeroplan")

Inserting data at specific position in XML

I want to read an XML file and match tag </contrib-group> and write a string after this tag
string Final = File.ReadAllText(Npath);
string Oxml = path + "\\" + Oword + ".abs.xml";
if (File.Exists(Oxml))
{
StreamReader xml = new StreamReader(Oxml,Encoding.UTF8);
string xmltag = xml.ReadToEnd();
//File.OpenWrite(Oxml);
xml.Close();
StreamWriter write = new StreamWriter(Oxml, true, Encoding.UTF8);
Match tag = Regex.Match(xmltag, #"</contrib-group>");
if (tag.Success == true)
{
write.WriteLine(Environment.NewLine);
write.Write(Final);
}
}
So I need to write the string Final to the XML file called Oxml after the matched XML tag </contrib-group>
If you are willing to save the new content as a valid XML file which you can work with, you should use the XML classes for that approach, this should look like this (untested):
XmlDocument doc = new XmlDocument();
doc.Load("YourFile.xml");
XmlElement root = doc.DocumentElement;
XmlNodeList elemList = root.GetElementsByTagName("contrib-group");
for (int i=0; i < elemList.Count; i++)
{
XmlNode xnode = elemList[i];
XmlNode xnodeParent = xnode.ParentNode;
XMLNode newNode = doc.CreateNode(XmlNodeType.Element, "NodeName", "");
newNode.InnerText = "ContentInsideTheNode";
xnodeParent.InsertAfter(newNode, xnode);
}
doc.Save("YourFile.xml");
If you only need to replace the string for other purposes than saving it where having a valid XML is not an issue you can just handle it as a string and use the String.Replace (String, String) Method
string searchedTag = #"</contrib-group>";
string tagAndNewContent = #"</contrib-group>" + newContent;
string fileContentString = File.ReadAllText("YourFile.xml");
string ouput = fileContentString.Replace(searchedTag, tagAndNewContent);

Enumerating Linq.Xelement

How to adjust this code to work when RESPONSE is no more string but Linq.Xelement?
String response = "anyxml data";
XmlDocument xmlDocument = LoadXMLDocument(response);
XmlNodeList nodeList = xmlDocument.GetElementsByTagName("fql_query_response");
if (nodeList != null && nodeList.Count > 0)
{
if (nodeList[0].HasChildNodes)
{
XmlNodeList results = xmlDocument.GetElementsByTagName("event_member");
Dictionary<string, EventUser> eventUserDict = new Dictionary<string, EventUser>();
foreach (XmlNode node in results)
{
myuids.Add(Int64.Parse(node.FirstChild.InnerText));
}
}
Do you mean you want to create an XmlDocument from an XElement?
The simplest way to do that may well be this:
XmlDocument doc = new XmlDocument();
using (XmlReader reader = element.CreateReader())
{
doc.Load(reader);
}
However, I have to say the code would probably be simpler if you just converted it all to LINQ to XML, which is generally a nicer API to start with. Is there any reason why you want to stay with XmlDocument?
You can use XElement.ToString() to create an XML string from the XElement which you can load into your XmlDocument:
XmlDocument xmlDocument = LoadXMLDocument(yourXElement.ToString());

Categories