Pasting xml to console - c#

I need to get data SHILS_V from XML file. I read .xml
XML code for example:
<SVED_PR_GS>
<ZGLV>
<VERSION>99</VERSION>
<DATA>9999</DATA>
<FILENAME>1234</FILENAME>
<FIRSTNAME>1234</FIRSTNAME>
</ZGLV>
<SVD>
<CODE></CODE>
<YEAR></YEAR>
<MONTH></MONTH>
</SVD>
<SV_PR_GS>
<OBSV>
<N_ZAP>1</N_ZAP>
<MO_SV_V>12345</MO_SV_V>
<SNILS_V>123456789</SNILS_V>
</OBSV>
</SV_PR_GS>
</SVED_PR_GS>
My code to read xml:
XmlDocument xml = new XmlDocument();
xml.Load(filename);
Console.WriteLine("this");
XmlNodeList nodes = xml.GetElementsByTagName("SVED_PR_GS/SV_PR_GS");
foreach (XmlNode n in nodes)
{
Console.WriteLine("in loop");
XmlNode snils_v = n["OBSV/SNILS_V"];
Console.WriteLine("Snils V: " + snils_v);
}
Where is the problem?
How to get the information from SNILS_V?

GetElementsByTagName expects a tagname, not an XPath expression, "SV_PR_GS" will work there. And the same goes for the indexer of your XmlNode instance called n, this XPath will not work n["OBSV/SNILS_V"], use a tagname there as well but you have to handle the extra OBSV child there.
Here is your adapted code that produces output for me:
XmlNodeList nodes = xml.GetElementsByTagName("SV_PR_GS");
foreach (XmlNode n in nodes)
{
Console.WriteLine("in loop");
// first get the OBSV element
XmlNode obsv = n["OBSV"];
// now we can reach the other childs
XmlNode snils_v = obsv["SNILS_V"];
// Value will be null for XmlElement types, use InnerText instead
Console.WriteLine("Snils V: {0}" , snils_v.InnerText);
}
Notice that the Value property will return null for XmlNode that are of type XmlElement. In the XmlNode.Value documentation it is stated:
null. You can use the XmlElement.InnerText or XmlElement.InnerXml properties to access the value of the element node.
As your SNILS_V element seem to contain just a value InnerText is appropriate here.

To select a single node from XML. You need to access that object using SelectSingleNode method.
xml.SelectSingleNode("xpath for node")
To get collection of nodes you can write
xml.SelectNodes("xpath for node collection")

You should be able to get the value as follows:
XmlDocument xml = new XmlDocument();
xml.Load(filename);
Console.WriteLine("this");
XmlNodeList nodes = xml.GetElementsByTagName("OBSV");
foreach (XmlNode n in nodes)
{
Console.WriteLine("in loop");
XmlNode snils_v = n.SelectSingleNode("SNILS_V");
Console.WriteLine("Snils V: " + snils_v.InnerText);
}

Related

Failing to read value XML attribute in C#

I am trying to read a file produced by another developer. The file looks something like this. I am trying to read in the value for 'ProfileName', but when I look at the object in memory, I see null for the Value (capital V) attribute. The only place I can see the string "GolfLeague-Dual" is in the outerxml attribute, but I would have to parse through a bunch of just to get it.
<?xml version="1.0"?>
<TopNode>
<ProfileSettings>
<ProfileName value="GolfLeague-Dual" />
</ProfileSettings>
</TopNode>
Here is my code to try to read this:
XmlDocument doc = new XmlDocument();
doc.Load(directory + #"\Settings.xml");
XmlElement root = doc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("//ProfileSettings");
foreach (XmlNode node in nodes) {
Console.WriteLine(node["ProfileName"].Value);
}
Your code is trying to get the inner value of the node, not an attribute called value. Try this instead...
foreach (XmlNode node in nodes) {
Console.WriteLine(node["ProfileName"].Attributes["value"].Value);
}
Here's a working dotnetfiddle...
https://dotnetfiddle.net/pmJKbX

return xml node that do not have specific child elements

I have the following code which is returning all nodes and thier values.
I only want to return nodes that do no have certain child nodes.
MY code base I am working from is
XmlNodeList nodelist = xmlDoc.SelectNodes("//DAV:schemata/DAV:classschema[#name='Tapestry']/DAV:propschema/DAV:*", nsmgr);
foreach (XmlNode node in nodelist)
{
strNode = node.Name;
strValue = node.InnerText;
responseString += strNode + " " + strValue + "\r\n ";
}
return responseString;
So I only what to return /propschema/* if the /propschema/ child does not contain a certain child node. For my example i do not want to return the propshema node if there is a child node of or
I had though I should be using something like
XmlNodeList nodelist = xmlDoc.SelectNodes("//DAV:schemata/DAV:classschema[#name='Tapestry']/DAV:propschema/DAV:*[not (count[system>0])", nsmgr);
But that is failing with an error of invalid token
'//DAV:schemata/DAV:classschema[#name='Tapestry']/DAV:propschema/DAV:*[not (count[system>0])' has an invalid token.
What am I doing wrong here? Am I missing syntax, "", or something else?
I have determined that if I can use a filter in the XPATH I would be applying it at the wrong point.
I want to return all propschema nodes and thier children except if the proschema had a child node of . So I need to put the filer earlier
XmlNodeList nodelist = xmlDoc.SelectNodes("//DAV:schemata/DAV:classschema[#name='Tapestry']/DAV:propschema[filter for system]/DAV:*", nsmgr);
But whenever I try to use a 'not' or type of filter I get a token error.
Is it possible to filter directly in the XPATH?

Why is my xml doc considered an element?

I am trying to load an xml file into an xmlDocument but receive an error that it cannot cast the xmlelement to a xmldocument why?
XML
<VR>
<SubscriberID>xxxx</SubscriberID>
<EmailAddress>m#gmail.com</EmailAddress>
<FirstName>m</FirstName>
<LastName>x</LastName>
<State>CO</State>
<Country/>
<BirthDate>11/16/3004</BirthDate>
<SendEmail>False</SendEmail>
<Preference Value="true" Key="life"/>
<Preference Value="true" Key="yo"/>
</VR>
C# Test
preferenceHelper target = new preferenceHelper(); // TODO: Initialize to an appropriate value
XmlDocument docIn = new XmlDocument();
docIn.Load(#"C:/INTG/trunk/src/VRI.Integration.Email/Test/xmlIn.xml");
XmlDocument expected = null; // I know this will fail in the test, but it should compile, right?
XmlDocument actual;
actual = target.preferencesXmlDoc(docIn);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method.");
C# function:
public class preferenceHelper
{
public preferenceHelper() { }
XmlDocument docOut = new XmlDocument();
public XmlDocument preferencesXmlDoc(XmlDocument docIn)
{
foreach (XmlDocument root in docIn.SelectNodes("//VR"))
{
foreach (XmlDocument node in root.SelectNodes("//Preference"))
{
XmlNode Name = docIn.CreateElement("Name");
Name.InnerText = node.InnerText = node.Attributes["Key"].Value;
XmlNode Value = docIn.CreateElement("Value");
Value.InnerText = node.InnerText = node.Attributes["Value"].Value;
docOut.CreateElement("Property").AppendChild(Name).AppendChild(Value);
}
}
return docOut;
}
}
Error
Test method Test.preferenceHelperTest.preferencesXmlDocTest threw exception:
System.InvalidCastException: Unable to cast object of type 'System.Xml.XmlElement' to type 'System.Xml.XmlDocument'.
I will not be adding a namespace to the xmlIn, if this is required - how might I load in my xml File?
Where it fails: actual = target.preferencesXmlDoc(docIn);
Thanks
Your problems are in these statements:
foreach (XmlDocument root in SelectNodes(...))
foreach implicitly casts each value in the sequence to the type you specify. The statement is expanded to:
using(var e = sequence.GetEnumerator())
{
while (e.MoveNext())
{
XmlDocument v = (XmlDocument)e.Current;
// loop body
}
}
The reason this is crashing with an InvalidCastException is that the type of node you're selecting is XmlElement, not XmlDocument. To fix the issue, simply switch the type in your foreach statement to XmlElement.
You can also improve readability by using XPath to reach the Preference elements, replacing both loops with a single:
foreach (XmlElement node in docIn.SelectNodes("/VR/Preference"))
Your outer SelectNodes loop is actually completely redundant because //Preference will get all Preference descendants from the root of the document already, not just from that specific child VR.
The proplem is here:
foreach (XmlDocument root in docIn.SelectNodes("//VR"))
and here:
foreach (XmlDocument node in root.SelectNodes("//Preference"))
XmlNode.SelectNodes() returns an XmlNodeList, which is an IEnumerable of XmlNodes. It will not contain any XmlDocuments.
So do this:
foreach (XmlNode root in docIn.SelectNodes("//VR"))
and this:
foreach (XmlElement node in root.SelectNodes("//Preference"))
XmlDocument.SelectNodes("//VR") returns an XmlNodeList, not an XmlDocument. So at the least you need to change your code to:
public XmlDocument preferencesXmlDoc(XmlDocument docIn)
{
foreach (XmlNode root in docIn.SelectNodes("//VR"))
{
foreach (XmlNode node in root.SelectNodes("//Preference"))
{
A document usually has a header:
<?xml version="1.0"?>
Without the header it is considered an element.
Try adding one.

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)

Help with looping through an XML in C#

I have an xml that looks like this
<words>
<word>word1</word>
<word>word2</word>
<word>word3</word>
<word>word4</word>
</words>
I would like to loop through the "word" tags and just output the innertext for now.
how would I do this?
here is what i am doing now but is says the list of nodes count is 1
string _badWordFileDocPath = //my file path;
XmlDocument badWordDoc = new XmlDocument();
badWordDoc.Load(_badWordFileDocPath);
XmlElement root = badWordDoc.DocumentElement;
XmlNodeList nodes = root.SelectNodes("/words");
foreach(XmlNode node in nodes)
{
Console.WriteLine(node.InnerText);
}
Thanks!
You are selecting the root words node itself, rather than the child word nodes. Add /word to your XPath:
XmlNodeList nodes = root.SelectNodes("/words/word");
You need to move down the node tree one more layer:
foreach(XmlNode node in nodes)
{
XmlNodeList innerNodes = node.SelectNodes("/word");
foreach(Xmlnode innerNode in innerNodes )
{
Console.WriteLine(innerNode.InnerText);
}
}
I'd recommend using the classes in System.Xml.Linq for this task:
XElement wordsElement = XElement.Parse(yourXmlText);
var words = from w in wordsElement.Elements("word")
select w.Value;
You are missing /word in your XPath.
You can also use Linq (XDocument) to fetch the data.

Categories

Resources