简体   繁体   English

c#使用XElement的元素元素

[英]c# Elements of elements using XElement

Not sure how I'm supposed to do this.不知道我该怎么做。

Here's the XML I'm working with:这是我正在使用的 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>

I'm writing a function that passes a value for item_type and item_type2, and returns the list of property values for that combination.我正在编写一个函数,该函数传递 item_type 和 item_type2 的值,并返回该组合的属性值列表。

Here's what I have.这就是我所拥有的。 It throws a "Object not set to an instance of an object" exception at the point noted.它在指出的点抛出“对象未设置为对象的实例”异常。

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

I KNOW this doesn't make sense - but I can't make it make sense.我知道这没有意义 - 但我无法让它有意义。

I would do it this way:我会这样做:

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

I guess you want something with XPath query like the following:我猜你想要一些带有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);

Do not forget to include using System.Xml.XPath;不要忘记包含using System.Xml.XPath; here is XPathEvaluate defined.这里定义了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));
}

Similar to many of the above solutions, but uses a direct path to the data and uses SelectMany to transform the result into a single collection - ie will work if you have duplicates for item1 and item2.与上述许多解决方案类似,但使用数据的直接路径并使用SelectMany将结果转换为单个集合 - 即如果您有 item1 和 item2 的重复项,它将起作用。

In case a VB'er needs help with something similar如果 VB'er 需要类似的帮助

    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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM