How to select xml root node when root node has attribute? - c#

I am trying to select all the child nodes of root node of an xml document using XPath query.
My xml file looks something like following :
<?xml version="1.0" encoding="UTF-8" ?>
<root>
<automotive_industry>
<automotive />
<rail_global_services />
</automotive_industry>
</root>
AND
<?xml version="1.0" encoding="UTF-8" ?>
<root xmlns="http://www.my_department.my_company.com/project_name">
<automotive_industry>
<automotive />
<rail_global_services />
</automotive_industry>
</root>
C# Code to select root node is as follows :
XmlDocument gazetteDocument = new XmlDocument();
gazetteDocument.Load(xmlFilePath);
XmlNodeList allNodes = gazetteDocument.SelectNodes("root");
This code works fine, it selects all the child nodes of root node when root node does not have any attribute that is, it works for 1st xml file but does not work for 2nd xml file because 2nd file has xmlns attribute.
Does anyone knows how to select all the child nodes of root node when root node has attributes??
EDIT :
I found one XPath query : /* This query selects root node no matter whether it has any attribute or not. Once root node is selected, I can iterate through its all the child nodes .

Although the namespace in your XML document is fine, you need to use it in your SelectNodes.
Use this code for your second XML:
XmlDocument gazetteDocument = new XmlDocument();
gazetteDocument.Load(xmlFilePath);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(gazetteDocument.NameTable);
nsmgr.AddNamespace("ns", "http://www.my_department.my_company.com/project_name");
XmlNodeList allNodes = gazetteDocument.SelectNodes("ns:root", nsmgr);
The better way would be to use XDocument and corresponding classes. They are a lot easier to work with.

I don't know the old xml methods of C#, but you could always open the file to read as normal text, and then read to the first node and parse it however you like.

You can use GetElementsByTagName method below are the snippet of my code
XmlDocument gazetteDocument = new XmlDocument();
gazetteDocument.Load(xmlFilePath);
XmlNodeList allNodes = gazetteDocument.GetElementsByTagName("root");

Related

How do I edit Node Values in an Xml File with C#

I am trying to change the values in a Farming simulator 22 savegame xml file from C# in visual studio. There are a lot of nodes so I have reduced them to make things easier. I want to know how to replace the value in the node using C# with out having to create and rebuild the xml file from scratch.
the path to the xml file is: (C:\Users\Name\Documents\My Games\FarmingSimulator2022\savegame1\careerSavegame.xml)
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<careerSavegame revision="2" valid="true">
<settings>
<savegameName>My game save</savegameName>
<creationDate>2022-05-03</creationDate>
<mapId>MapFR</mapId>
<mapTitle>Haut-Beyleron</mapTitle>
<saveDateFormatted>2022-08-22</saveDateFormatted>
<saveDate>2022-08-22</saveDate>
<resetVehicles>false</resetVehicles>
</careerSavegame>
You can use the System.Xml.Linq namespace to access the xml file. This will load the file in the memory.
There is one class inside it, XDocument, that represents the xml document.
String filePath = "C:\Users\Name\Documents\My Games\FarmingSimulator2022\savegame1\careerSavegame.xml"
XDocument xdoc = XDocument.Load(filePath);
var element = xdoc.Elements("MyXmlElement").Single();
element.Value = "foo";
xdoc.Save("file.xml");
You can set the element variable as per the one which is needed to be replaced.
Through some research I found the solution to editing the values within the nodes. In this example I only change the value of savegameName, but it will be the same for the rest.
//Routing the xml file
XmlDocument xmlsettings = new XmlDocument();
xmlsettings.Load(#"D:\careerSavegame.xml");
//Setting values to nodes through innertext
String FarmNameSetting = "Martek Farm";
XmlNode savegameNamenode =
xmlsettings.SelectSingleNode
("careerSavegame/settings/savegameName");
savegameNamenode.InnerText = FarmNameSetting;

Cannot find a way to get a child node from an XMLNodeList by text

This is killing me, I have an XMLDocument and I need to be able to get the text value of certain nodes out but everything I try fails. Given the below XML document, I need to get things like the ID of the patient, Last Name, etc.
<Message xmlns="http://" version="010" release="006">
<Header>
<To Qualifier="C">1306841101</To>
<From Qualifier="P">8899922</From>
</Header>
<Body>
<RxFill>
<Patient>
<Identification>
<ID>193306093523</ID>
<ID3>111223333</ID3>
</Identification>
<Name>
<LastName>Smith</LastName>
<FirstName>Jane</FirstName>
</Name>
</Patient>
</RxFill>
</Body>
I can get the actual NodeList of 'Patient' like so:
XmlNode root = oDoc.DocumentElement;
oDoc.GetElementsByTagName("Patient")
but then I am stuck, if I then try to get a child node, the xpath never finds them.
for example:
oDoc.GetElementsByTagName("Patient")[0].SelectSingleNode("Identification")
comes up null even though I can see in the debugger that "Identification" is the FirstChild. I have added slash(es) as well: "//Identification" and no joy.
I can, however, get to it from the document:
oDoc.GetElementsByTagName("Identification")
but that won't work because I may have other tags in the document like that; I only want the Identification tag that belongs to the Patient.
I have tried looping through all the children to find them but that seems very inefficient.
Any ideas?
You should include the namespace in the XPath. You can do this using an XmlNamespaceManager:
XmlNode root = oDoc.DocumentElement;
XmlNode patient = oDoc.GetElementsByTagName("Patient")[0];
XmlNamespaceManager nsm = new XmlNamespaceManager(new NameTable());
nsm.AddNamespace("ns", "http://");
XmlNode identification = patient.SelectSingleNode("ns:Identification", nsm);
string id = identification.SelectSingleNode("ns:ID", nsm).InnerText;

Issue with loading xml in C# containing google kml

I am trying to access the second element in this xml (google kml type) of file and the issue I am having is I get returned null values for my code unless I remove out the <kml xmlns="http://earth.google.com/kml/2.0"> and the related close from the source file. Here is the code I'm using. (mind you this works if I remove the specified line so what I'm looking for is a clean way to process this file without editing the supplied source file.)
XmlDocument doc = new XmlDocument();
doc.Load("2014_q2.xml");
XmlNodeList xnlNodes = doc.SelectNodes("/kml/Document/Folder");
var Node2Use = xnlNodes.Item(1);
here is the top of the source file:
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.0">
<Document>
<open>1</open>
<Folder>
<name>Pts_2014_q3_point Drawing</name>
<Placemark>
<description>HOLTSVILLE</description>
<name>00501</name>
<Style>
<IconStyle>
<color>ffc0c0c0</color>
I have a break on the var Node2Use = xnlNodes.Item(1); line so I can see the contents and thats where I see that I have a zero value where I should have 2 for Folder (like mentioned I get the 2 when I remove out that kml tagged line.)
You need to include the namespace. Something like this:
XmlDocument doc = new XmlDocument();
doc.Load("2014_q2.xml");
XNamespace ns = "http://earth.google.com/kml/2.0";
XmlNodeList xnlNodes = doc.SelectNodes(ns + "/kml/Document/Folder");

XML node madness

I got about 1100 xml files that are read programmatically which works fine, except for one node in around 200 of those files. Redownloaded the data but still the same files aren't working. Maybe someone can help and spot the difference between the working and the non-working.
It's just a matter of one node (rest of that document works for all files) and its inner text.
Working node:
<sequence length="55" mass="6372" checksum="31681CC3DAC0C5D6" modified="2007-01-23" version="2">
MAKGIREKIKLVSSAGTGHFYTTTKNKRTKPEKLELKKFDPVVRQHVIYKEAKIK
</sequence>
Not working node:
<sequence length="394" mass="43314" checksum="6EDA60255F43358F" modified="2007-01-23Z" version="2">
MSKEKFERTKPHVNVGTIGHVDHGKTTLTAAITTVLAKTYGGAARAFDQIDNAPEEKARGITINTSHVEYDTPTRHYAHVDCPGHAD YVKNMITGAAQMDGAILVVAATDGPMPQTREHILLGRQVGVPYIIVFLNKCDMVDDEELLELVEMEVRELLSQYDFPGDDTPIVRGSALKALEGDAEWEAKILELAGFLDSYIPEPERAIDKPFLLPIEDVFSISGRGTVVTGRVERGIIKVGEEVEIVGIKETQKSTCTGVEMFRKLLDEGRAGENVGVLLRGIKREEIERGQVLAKPGTIKPHTKFESEVYILSKDEGGRHTPFFKGYRPQFYFRTTDVTGTIELPEGVEMVMPGDNIKMVVTLIHPIAMDDGLRFAIREGGRTVGAGVVAKVLS
</sequence>
Code that's reading creating the file:
XmlDocument XMLdoc = new XmlDocument();
XMLdoc.LoadXml(Result);
XMLdoc.Save(Datapath);
Code that's reading the file:
XmlDocument XMLdoc = new XmlDocument();
XMLdoc.Load(Datapath);
XmlNamespaceManager nsmgr = new XmlNamespaceManager(XMLdoc.NameTable);
nsmgr.AddNamespace("ns", "http://uniprot.org/uniprot");
Just in case that might be the reason. XML code was verified as well-formed even with the different/broken node.
To make it relevant to others: What can happen in XML files that they won't get read anymore?

How to add Schema location and XSI dynamically to an XML file

Hi all i am creating an application to generate an XML file dynamically. In this i would like to add schemalocation and XSI to the XML Root how can i do this. I would like to add the following
xmlns="http://www.irs.gov/efile"
xsi:SchemaLocation="http://www.irs.goc/efile ReturnData941.xsd"
and
xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance"
This is my sample XML code that was generated dynamically
XmlDocument doc = new XmlDocument();
XmlNode docNode = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
doc.AppendChild(docNode);
XmlNode returnData = doc.CreateElement("ReturnData");
XmlAttribute documnetCount = doc.CreateAttribute("documentCount"); // after this i would like to add that schema
returnData.Attributes.Append(documnetCount);
So that i should get my XML as follows
<?xml version="1.0" encoding="UTF-8"?>
<ReturnData documentCount="" xsi:SchemaLocation="http://www.irs.goc/efile ReturnData941.xsd" xmlns="http://www.irs.gov/efile" xmlns:xsi="http://www.w3.org/2001/XMLSchema-Instance" />
I think you just need add a attribute like
XmlAttribute attr = doc.CreateAttribute("xsi", "schemaLocation", " ");
attr.Value = "http://www.irs.goc/efile ReturnData941.xsd";
returnData.Attributes.Append(attr);
I wonder if this is the best way of approaching things? Many validation APIs allow you to specify the schema location and instance document location independently, and that's likely to be more efficient than storing the schema location within the instance.
Generally I'm sceptical about xsi:schemaLocation anyway. If you're validating the instance, that's often because you don't trust it, and if you don't trust it, why should you trust its xsi:schemaLocation?

Categories

Resources