Failing to read value XML attribute in C# - 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

Related

Pasting xml to console

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);
}

Can't find a certain node in XML

My problem is that I can't seem to get a list of nodes I need. I have tried multiple solutions and it doesn't seem to work. This is a part of my xml file:
<findItemsByCategoryResponse xmlns="http://www.ebay.com/marketplace/search/v1/services">
<ack>Success</ack>
<version>1.13.0</version>
<timestamp>2016-08-23T07:33:22.497Z</timestamp>
<searchResult count="100">
<item>
<itemId>152210133431</itemId>
<title>...</title>
<globalId>EBAY-GB</globalId>
<primaryCategory>
<categoryId>218</categoryId>
<categoryName>Magic the Gathering</categoryName>
</primaryCategory>
<galleryURL>
http://thumbs4.ebaystatic.com/m/meIDrVqhmbpQMYCxzeUvR9Q/140.jpg
</galleryURL>
<viewItemURL>
http://www.ebay.co.uk/itm/MTG-See-Unwritten-Khans-Tarkir-MYTHIC-MINT-/152210133431
</viewItemURL>
<paymentMethod>PayPal</paymentMethod>
<autoPay>false</autoPay>
<location>London,United Kingdom</location>
<country>GB</country>
<shippingInfo>
<shippingServiceCost currencyId="GBP">1.1</shippingServiceCost>
<shippingType>Flat</shippingType>
<shipToLocations>GB</shipToLocations>
</shippingInfo>
<sellingStatus>
<currentPrice currencyId="GBP">0.5</currentPrice>
<convertedCurrentPrice currencyId="GBP">0.5</convertedCurrentPrice>
<bidCount>0</bidCount>
<sellingState>Active</sellingState>
<timeLeft>P0DT0H19M12S</timeLeft>
</sellingStatus>
<listingInfo>
<bestOfferEnabled>false</bestOfferEnabled>
<buyItNowAvailable>false</buyItNowAvailable>
<startTime>2016-08-18T07:52:34.000Z</startTime>
<endTime>2016-08-23T07:52:34.000Z</endTime>
<listingType>Auction</listingType>
<gift>false</gift>
</listingInfo>
<condition>
<conditionId>1000</conditionId>
<conditionDisplayName>New</conditionDisplayName>
</condition>
<isMultiVariationListing>false</isMultiVariationListing>
<topRatedListing>false</topRatedListing>
</item>
</searchResult>
<paginationOutput>...</paginationOutput>
<itemSearchURL>...</itemSearchURL>
</findItemsByCategoryResponse>
Normally there are 100 item nodes in this xml file, I just shorted the file. I tried to get the ''item'' nodes and everything inside in a XmlNodeList, but when I debug it says it contains 0 items. After this I want to retrieve some data, as you can see in the code. Note: I tried a lot of xpath values!
Here is the code I used:
XmlDocument xmlText = new XmlDocument();
xmlText.Load(basicUrl);
XmlElement root = xmlText.DocumentElement;
XmlNodeList xnList = root.SelectNodes("//item");
foreach(XmlNode item in xnList)
{
string title = item["title"].InnerText;
Console.WriteLine(title);
}
XPath Expressions are always namespace aware (if the Element has a Namespace then the XPath must reference it by namespace). Also, in XPath expressions, the 'default' namespace is always in the URI "". In your case you should do something like this :
XmlDocument xmlText = new XmlDocument();
xmlText.Load(yourXml);
XmlElement root = xmlText.DocumentElement;
XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlText.NameTable);
nsmgr.AddNamespace("t", "http://www.ebay.com/marketplace/search/v1/services");
XmlNodeList xnList = xmlText.SelectNodes("//t:item", nsmgr);
foreach (XmlNode item in xnList)
{
string title = item["title"].InnerText;
Console.WriteLine(title);
}
SelectNodes with namespace :
https://msdn.microsoft.com/en-US/library/4bektfx9(v=vs.110).aspx

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.

Read first root node from XML

I work with three kinds of XML files :
Type A:
<?xml version="1.0" encoding="UTF-8"?>
<nfeProc versao="2.00" xmlns="http://www.portalfiscal.inf.br/nfe">
</nfeProc>
Tyepe B:
<?xml version="1.0" encoding="UTF-8"?>
<cancCTe xmlns="http://www.portalfiscal.inf.br/cte" versao="1.04">
</cancCTe>
Type C:]
<?xml version="1.0" encoding="UTF-8"?>
<cteProc xmlns="http://www.portalfiscal.inf.br/cte" versao="1.04">
</cteProc>
I have try with this code to read the first node :
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(#"C:\crruopto\135120068964590_v01.04-procCTe.xml");
XmlNodeList ml = xmlDoc.GetElementsByTagName("*");
XmlElement root = xmlDoc.DocumentElement;
exti = root.ToString();
but dont return anything i want to read the first node , need to know if the file is nfeProc ,canCTE or cteProc
The second question is how i get the value from "value" in the same tag???
Thanks
From this post:
//Root node is the DocumentElement property of XmlDocument
XmlElement root = xmlDoc.DocumentElement
//If you only have the node, you can get the root node by
XmlElement root = xmlNode.OwnerDocument.DocumentElement
I would suggest using XPath. Here's an example where I read in the XML content from a locally stored string and select whatever the first node under the root is:
XmlDocument doc = new XmlDocument();
doc.Load(new StringReader(xml));
XmlNode node = doc.SelectSingleNode("(/*)");
If you aren't required to use the XmlDocument stuff, then Linq is your friend.
XDocument doc = XDocument.Load(#"C:\crruopto\135120068964590_v01.04-procCTe.xml");
XElement first = doc.GetDescendants().FirstOrDefault();
if(first != null)
{
//first.Name will be either nfeProc, canCTE or cteProc.
}
Working with Linq to XML is the newest and most powerful way of working with XML in .NET and offers you a lot more power and flexibility than things like XmlDocument and XmlNode.
Getting the root node is very simple:
XDocument doc = XDocument.Load(#"C:\crruopto\135120068964590_v01.04-procCTe.xml");
Console.WriteLine(doc.Root.Name.ToString());
Once you have constructed an XDocument you don't need to use any LINQ querying or special checking. You simply pull the Root property from the XDocument.
Thanks i have solved this way the first part
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(nomear);
XmlNodeList ml = xmlDoc.GetElementsByTagName("*");
XmlNode primer = xmlDoc.DocumentElement;
exti = primer.Name;
First, to be clear, you're asking about the root element, not the root node.
You can use an XmlReader to avoid having to load large documents completely into memory. See my answer to a how to find the root element at https://stackoverflow.com/a/60642354/1307074.
Second, once the reader is referencing the element, you can use the reader's Name property to get the qualified tag name of the element. You can get the value as a string using the Value property.

Get Child Nodes from an XML File

I have an XML File like below
<Attachment>
<FileName>Perimeter SRS.docx</FileName>
<FileSize>15572</FileSize>
<ActivityName>ActivityNamePerimeter SRS.docx</ActivityName>
<UserAlias>JameelM</UserAlias>
<DocumentTransferId>7123eb83-d768-4a58-be46-0dfaf1297b97</DocumentTransferId>
<EngagementName>EAuditEngagementNameNew</EngagementName>
<Sender>JameelM#orioninc.com</Sender>
</Attachment>
I read these xml file like below
var doc = new XmlDocument();
doc.Load(files);
foreach (XmlElement pointCoord in doc.SelectNodes("/Attachment"))
{
}
I need to get each child node value inside the Attachment node. How can i get these xml elements from the xml node list?
I need to get each child node value inside the Attachment node.
Your question is very unclear, but it looks like it's as simple as:
foreach (XmlNode node in doc.DocumentElement.ChildNodes)
{
}
After all, in the document you've shown us, the Attachment is the document element. No XPath is required.
As an aside, if you're using .NET 3.5 or higher, LINQ to XML is a much nicer XML API than the old DOM (XmlDocument etc) API.
try this
var data = from item in doc.Descendants("Attachment")
select new
{
FileName= item.Element("FileName").Value,
FileSize= item.Element("FileSize").Value,
Sender= item.Element("Sender").Value
};
foreach (var p in data)
Console.WriteLine(p.ToString());
var doc = new XmlDocument();
doc.Load(files);
foreach (XmlElement pointCoord in doc.SelectNodes("/Attachment"))
{
if(pointCoord!=null)
{
var valueOfElement=pointCoord.InnerText;
}
}
if you want to run conditional logic against the element names (UserAlias, etc) then use the Name property of the XmlElement.

Categories

Resources