This question must be easy, but I faced a problem,
which I can't deal with.
No matter what I try I am unable to parse this xml with linq and get the xml value.
The error is "System.Collections.Generic.IEnumerable' does not contain a definition for 'Element' and no extension method 'Element' accepting a first argument of type 'System.Collections.Generic.IEnumerable' could be found (are you missing a using directive or an assembly reference?)"
I want to find the Xelement attribute.value which children have a concrete attribute.value.
How can I get the attribute.value?
thanks
xml
<submitInfo>
<setting name="file1" file ="example3.c" info ="open it!" serializeAs="String">
<add name="file11" program="example2.c" />
<add name="file12" value="example1.c" />
<value />
<setting name="file2" file ="example23.c" info ="open it!" serializeAs="String">
<add name="file21" program="example22.c" />
<add name="file22" value="example21.c" />
<value />
</setting>
</submitInfo>
code:
var title1 = from q in doc.Element("content").Element("submitInfo").Elements("setting")
select q;
foreach (var t1 in title1)
{
Console.WriteLine(
String.Format(
name = title1.Element("name").Value,
file= title1.Element("file").Value,
info= title1.Attribute("info").Value));
}
//get setting info
var title = from p in doc.Element("content").Element("submitInfo").Element("setting").Elements("add")
select p;
foreach (var t1 in title)
{
Console.WriteLine(
String.Format(
name = title1.Element("name").Value,
value = title1.Element("program").Value));
This is one problem:
name = title1.Element("name").Value,
file= title1.Element("file").Value,
info= title1.Attribute("info").Value));
Look at your XML:
<setting name="file1" file ="example3.c" info ="open it!" serializeAs="String">
<add name="file11" program="example2.c" />
<add name="file12" value="example1.c" />
<value />
</setting>
It doesn't have a name or file element - those are attributes. So you want something like:
string name = t1.Attribute("name");
string file = t1.Attribute("file");
string info = t1.Attribute("info");
Note that this is using t1, not title1 - otherwise you're asking for the data from the query, rather than for the specific element of the query.
Additionally, you really don't need a query expression here. Just use:
var title1 = doc.Element("content").Element("submitInfo").Elements("setting");
Another problem is that you're currently calling string.Format with three assignments inside. I suspect you actually wanted:
Console.WriteLine("{0} {1} {2}", t1.Attribute("name"),
t1.Attribute("file"), t1.Attribute("info"));
Related
I have an xml document that I want to obtain attributes from
Here is the XML:
<Translations>
<Product Name="Room" ID="16">
<Terms>
<Term Generic="Brand" Product="Sub Category" />
<Term Generic="Range" Product="Brand" />
</Terms>
</Product>
<Product Name="House"" ID="29">
<Terms>
<Term Generic="Category" Product="Product Brand" />
<Term Generic="Brand" Product="Category Description" />
<Term Generic="Range" Product="Group Description" />
<Term Generic="Product" Product="Product Description" />
</Terms>
</Product>
</Translations>
Here is my current Linq query
public static string clsTranslationTesting(string GenericTerm, int ProductID)
{
const string xmlFilePath = "C:\\Dev\\XMLTrial\\XMLFile1.xml";
var xmlDocument = XDocument.Load(xmlFilePath);
var genericValue =
from gen in xmlDocument.Descendants("Product")
where gen.Attribute("ID").Value == ProductID.ToString()
select gen.Value.ToString();
}
The error that I am having is when I pass data into the method, the method loads the xml from the file to the xmlDocument variable successfully. However when it executes the query it returns a value null. I want to obtain the ID value.
I'm a little lost with your question, but here's my attempt.
First thing is you need to change "Customer" to "Product". Your XML contains not a single instance of the word "Customer" so I think you have a typo there.
I don't know exactly what you want returned from the query (I assume just the entire matched node?). Try this:
var genericValue = xmlDocument.Descendants("Product")
.FirstOrDefault(x => x.Attribute("ID").Value == "16");
I made a fiddle here that shows it in action
I have an XML like:
<configuration>
<connectionStrings>
<add name="name1" value="value1">
<add name="name2" value="value2">
</connectionStrings>
<configuration>
In this i get
XmlNodeList nodeList = doc.GetElementsByTagName("connectionStrings");
foreach(XmlNode xn in nodeList)
{
var anode = xn.SelectSingleNode("add");
}
Here "var anode" is returning me right values of "name" attribute.
But when my xml is like:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<connectionStrings>
<add name="name1" value="value1">
<add name="name2" value="value2">
</connectionStrings>
<configuration>
I get anode as null.
Please help.
The following code works for me:
var xElement = XElement.Load("Sample.xml");
var elements = xElement.Elements().Elements();
foreach (var element in elements)
{
var name = element.Attribute("value").Value;
}
Please try this.
Note: The Sample.xml contains:
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<connectionStrings>
<add name="name1" value="value1"/>
<add name="name2" value="value2"/>
</connectionStrings>
</configuration>
The xml file which you posted didnot close properly. Above xml is properly formatted.
I have an XML which follow the following structure:
<model uir="model1">
<profile>
<profiles>
<timeseries>
<value double="24.7" index="2011-01-01 00:00" />
<value double="24.5" index="2011-01-02 00:00" />
<value index="2011-04-23 00:00" /> //Here for some reason i must have double=null
<value index="2011-04-24 00:00" />
<value double="24.7" index="2011-01-01 00:00" />
<value double="24.5" index="2011-01-02 00:00" />
</timeseries>
</profile>
</profiles>
</model>
<model uir="model2">
<profile>
<profiles>
<timeseries>
<value double="24.7" index="2011-01-01 00:00" />
<value double="24.5" index="2011-01-02 00:00" />
<value index="2011-04-23 00:00" /> //Here for some reason i must have double=null
<value index="2011-04-24 00:00" />
<value double="24.7" index="2011-01-01 00:00" />
<value double="24.5" index="2011-01-02 00:00" />
</timeseries>
</profile>
</profiles>
</model>
This that i want is to take the value of the attribute double and to store it in a list (or vector) for each model. When the node value hasn't an attribute double to insert a null. In first level i tried the following but when it reaches in a node with no attribute double stack.
using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
class MyClass
{
static void Main(string[] args)
{
string file = #"C:\RDMS.xml";
XDocment doc = XDocument.Load(file);
foreach (var item in doc.Descendants("value"))
{
Console.WriteLine(item.Attribute("double").Value);
}
Console.ReadKey();
}
}
You did not specify the error, but I am guessing you are getting a NullReferenceException? You need to check if item.Attribute actually returns a value.
var doubleAttr = item.Attribute("double");
if(doubleAttr == null) continue;
Console.WriteLine(item.Attribute("double").Value);
If that is not your problem, then please be more specific as to what your problem is.
Further clarification from trope's comment below:
...you are getting a NullReferenceException because nothing returns from item.Attribute("double") for the elements that lack that attribute, therefore you cannot then call .Value, as item.Attribute("double") is null, and you receive a NullReferenceException. This does not happen with your index attribute, because all of your "value" elements have index attributes...
You can check the result of Attribute(string) if it is null:
var attrib = item.Attribute("double");
if (attrib != null)
Console.WriteLine(attrib.Value);
else
Console.WriteLine("attribute not found!");
I'm trying to read in some XML data but I'm getting an error I've never spotted before. Can anyone shed some light on this?
The error:
Screen name: System.Xml.Linq.Extensions+c__Iterator5
UnityEngine.Debug:Log(Object)
HV_ReadSettingsFile:Update() (at Assets/_scripts/HV_ReadSettingsFile.cs:64)
Here is my code reading in the XML and is ultimately generating the error:
var xdoc = XDocument.Load(#"C:\\Test.xml");
var screen = xdoc.Descendants("Screen");
foreach (var Screen in screen)
{
HV_Screen _screen = new HV_Screen();
_screen.Name = Convert.ToString(Screen.Descendants("Name").Attributes("Name"));
Debug.Log("Screen name: " + _screen.Name);
}
And my XML sheet:
<Settings>
<Display_Settings>
<Screen>
<Name Name="Screen" />
<ScreenTag Tag="Screen Tag" />
<LocalPosition X="12" Y="81" Z="28" />
<Width Width="54" />
<Height Height="912" />
</Screen>
<Screen>
<Name Name="Screen" />
<ScreenTag Tag="Screen Tag" />
<LocalPosition X="32" Y="21" Z="28" />
<Width Width="54" />
<Height Height="912" />
</Screen>
</Display_Settings>
</Settings>
That's not an error. That's logging exactly what you've asked for. You've asked for all the Name attributes in all the Name elements... but then you're trying to log that sequence as a single value.
I think you want:
var screens = xdoc.Descendants("Screen");
foreach (var screen in screens)
{
HV_Screen _screen = new HV_Screen();
_screen.Name = (string) screen.Element("Name").Attribute("Name");
Debug.Log("Screen name: " + _screen.Name);
}
This is now looking for one element and one attribute per Screen element. Note that I've changed the variable names to follow normal .NET conventions, other than _screen as I don't know what HV_Screen is meant to be.
It's not really clear why you've got separate elements for Width, Height and Name, each with an attribute matching the element name - and ScreenTag nearly doing so. If the XML is under your control, you might consider either:
<Screen Name="Screen" Width="54" Height="912" Tag="Screen Tag">
<LocalPosition X="12" Y="81" Z="28" />
</Screen>
or perhaps:
<Screen>
<Name>Screen</Name>
<ScreenTag>Screen Tag</ScreenTag>
<LocalPosition X="12" Y="81" Z="28" />
<Width>54</Width>
<Height>912</Height>
</Screen>
Also, if you're trying to build a collection of HV_Screen items, you probably want to use a query rather than a foreach loop - but it's not clear what you're actually trying to do beyond logging debug information at the moment.
You can try to do:
var xdoc = XDocument.Load(#"C:\\test.xml");
List<string> lstScreen = xdoc.Descendants("Screen").Select(x => x.Element("Name").Attribute("Name").Value).ToList();
foreach (string name in lstScreen)
{
...
I hope help you!!
I have a program that updates a config file. For example, the config file may contain:
<configuration>
<userSettings>
<setting name="phoneNumber" serializeAs="String">
<value>123-456-7890</value>
</setting>
</userSettings>
</configuration>
To update this config file, I use the following:
XmlNode phoneNumberNode = theConfig.SelectSingleNode("configuration/userSettings/setting[#name='phoneNumber']");
phoneNumberNode.FirstChild.InnerText = this._cloudPublisherWebURL;
Now, during the update I want to update phoneNumber and address. Address may or may not be in the config file.
If SelectSingleNode is null, I would like to create a node with the given path and set its value.
XmlNode addressNode = theConfig.SelectSingleNode("configuration/userSettings/setting[#name='address']");
if(addressNode == null)
{
//..Create the node here
}
How can I create the node with value at the given path?
XmlNode addressNode = theConfig.SelectSingleNode("configuration/userSettings");
XmlNode setting = addressNode.Item(0).SelectSingleNode("configuration/userSettings/setting[#name='phoneNumber']");
setting.SetAttribute("name", "address"); //this is to change the name attribute value into address