c# Elements of elements 使用 XElement
c# Elements of elements using XElement
不确定我应该怎么做。
这是我正在使用的XML:
<configuration>
<tag1>
<interestingstuff>avalue</interestingstuff>
</tag1>
<tag2>
<item_type1 name="foo">
<item_type2 name="bar">
<property>value1</property>
<property>value2</property>
</item_type2>
<item_type2 name="pub">
<property>valueX</property>
<property>valyeY</property>
</item_type2>
<item_type1>
<item_type1 name="foo2">
<item_type2 name="pub">
<property>valueX</property>
</item_type2>
</item_type1>
</tag2>
</configuration>
我正在编写一个函数,它传递 item_type 和 item_type2 的值,以及 returns 该组合的 属性 值列表。
这是我的。它会在记录的位置抛出 "Object not set to an instance of an object" 异常。
ArrayList properties = new ArrayList();
XDocument config = new XDocument();
config = XDocument.Parse(XML_Text);
foreach (XElement item1 in config.Root.Element("tag2").Nodes())
{
if (item1.Attribute("name").Value.ToString() == passed_item1_value)
{
//this is where it's breaking
foreach (XElement item2 in item1.Elements("item_type2").Nodes())
{
if item2.Attribute("name").Value.ToString() == passed_item2_value)
{
foreach (XElement property in item2.Elements("property").Nodes())
{
properties.Add(property.Value.ToString());
}
break;
}
}
break;
}
}
我知道这没有意义 - 但我无法让它变得有意义。
我会这样做:
public IEnumerable<string> findValues(string item1, string item2)
{
config = XDocument.Parse(XML_Text)
var res = config.Descendants("item_type1")
.Where(x=>x.Attribute("name").Value == item1)
.Descendants("item_type2")
.Where(x=>x.Attribute("name").Value == item2);
return res.Descendants("property").Select(x=>x.Value);
}
我猜你想要像下面这样的 XPath 查询:
var path = string.Join("/",
"configuration",
"tag2",
string.Format("item_type1[@name='{0}']", passed_item1_value),
string.Format("item_type2[@name='{0}']", passed_item2_value),
"property");
var elements = (IEnumerable)config.XPathEvaluate(path);
var properties = elements.Cast<XElement>().Select(x => x.Value);
不要忘记包含 using System.Xml.XPath;
这里是 XPathEvaluate
定义的。
using System.Linq;
using System.Xml.Linq;
IEnumerable<string> GetProperties(XElement xml, string item1, string item2)
{
return xml.Element("tag2")
.Elements("item_type1").Where(x => x.Attribute("name").Value == item1)
.Elements("item_type2").Where(x => x.Attribute("name").Value == item2)
.SelectMany(x => x.Elements("property").Select(p => p.Value));
}
与上述许多解决方案类似,但使用数据的直接路径并使用 SelectMany
将结果转换为单个集合 - 也就是说,如果您有 item1 和 item2 的重复项,它将起作用。
万一 VB 的人需要类似的帮助
Dim xe As XElement
xe = <configuration>
<tag1>
<interestingstuff>avalue</interestingstuff>
</tag1>
<tag2>
<item_type1 name="foo">
<item_type2 name="bar">
<property>value1</property>
<property>value2</property>
</item_type2>
<item_type2 name="pub">
<property>valueX</property>
<property>valyeY</property>
</item_type2>
</item_type1>
<item_type1 name="foo2">
<item_type2 name="pub">
<property>valueX</property>
</item_type2>
</item_type1>
</tag2>
</configuration>
Dim passed_item1_value As String = "foo" 'for test
Dim passed_item2_value As String = "pub" 'for test
Dim ie As IEnumerable(Of String)
ie = (From el In xe.<tag2>.<item_type1>...<item_type2>
Where el.Parent.@name = passed_item1_value AndAlso el.@name = passed_item2_value
From sel In el...<property> Select sel.Value)
Return ie.ToArray
不确定我应该怎么做。
这是我正在使用的XML:
<configuration>
<tag1>
<interestingstuff>avalue</interestingstuff>
</tag1>
<tag2>
<item_type1 name="foo">
<item_type2 name="bar">
<property>value1</property>
<property>value2</property>
</item_type2>
<item_type2 name="pub">
<property>valueX</property>
<property>valyeY</property>
</item_type2>
<item_type1>
<item_type1 name="foo2">
<item_type2 name="pub">
<property>valueX</property>
</item_type2>
</item_type1>
</tag2>
</configuration>
我正在编写一个函数,它传递 item_type 和 item_type2 的值,以及 returns 该组合的 属性 值列表。
这是我的。它会在记录的位置抛出 "Object not set to an instance of an object" 异常。
ArrayList properties = new ArrayList();
XDocument config = new XDocument();
config = XDocument.Parse(XML_Text);
foreach (XElement item1 in config.Root.Element("tag2").Nodes())
{
if (item1.Attribute("name").Value.ToString() == passed_item1_value)
{
//this is where it's breaking
foreach (XElement item2 in item1.Elements("item_type2").Nodes())
{
if item2.Attribute("name").Value.ToString() == passed_item2_value)
{
foreach (XElement property in item2.Elements("property").Nodes())
{
properties.Add(property.Value.ToString());
}
break;
}
}
break;
}
}
我知道这没有意义 - 但我无法让它变得有意义。
我会这样做:
public IEnumerable<string> findValues(string item1, string item2)
{
config = XDocument.Parse(XML_Text)
var res = config.Descendants("item_type1")
.Where(x=>x.Attribute("name").Value == item1)
.Descendants("item_type2")
.Where(x=>x.Attribute("name").Value == item2);
return res.Descendants("property").Select(x=>x.Value);
}
我猜你想要像下面这样的 XPath 查询:
var path = string.Join("/",
"configuration",
"tag2",
string.Format("item_type1[@name='{0}']", passed_item1_value),
string.Format("item_type2[@name='{0}']", passed_item2_value),
"property");
var elements = (IEnumerable)config.XPathEvaluate(path);
var properties = elements.Cast<XElement>().Select(x => x.Value);
不要忘记包含 using System.Xml.XPath;
这里是 XPathEvaluate
定义的。
using System.Linq;
using System.Xml.Linq;
IEnumerable<string> GetProperties(XElement xml, string item1, string item2)
{
return xml.Element("tag2")
.Elements("item_type1").Where(x => x.Attribute("name").Value == item1)
.Elements("item_type2").Where(x => x.Attribute("name").Value == item2)
.SelectMany(x => x.Elements("property").Select(p => p.Value));
}
与上述许多解决方案类似,但使用数据的直接路径并使用 SelectMany
将结果转换为单个集合 - 也就是说,如果您有 item1 和 item2 的重复项,它将起作用。
万一 VB 的人需要类似的帮助
Dim xe As XElement
xe = <configuration>
<tag1>
<interestingstuff>avalue</interestingstuff>
</tag1>
<tag2>
<item_type1 name="foo">
<item_type2 name="bar">
<property>value1</property>
<property>value2</property>
</item_type2>
<item_type2 name="pub">
<property>valueX</property>
<property>valyeY</property>
</item_type2>
</item_type1>
<item_type1 name="foo2">
<item_type2 name="pub">
<property>valueX</property>
</item_type2>
</item_type1>
</tag2>
</configuration>
Dim passed_item1_value As String = "foo" 'for test
Dim passed_item2_value As String = "pub" 'for test
Dim ie As IEnumerable(Of String)
ie = (From el In xe.<tag2>.<item_type1>...<item_type2>
Where el.Parent.@name = passed_item1_value AndAlso el.@name = passed_item2_value
From sel In el...<property> Select sel.Value)
Return ie.ToArray