【问题标题】:Linq to XML Get parent element attribute value by querying it's childrenLinq to XML 通过查询子元素获取父元素属性值
【发布时间】:2012-03-20 05:42:38
【问题描述】:

我正在尝试构建一个 Linq to XML 查询,但还没有找到真正的解决方案。

这是我的 XML

<Nodes>
  <Node Text="Map" Value="Map">
    <Node Text="12YD" Value="12YD">
      <Node Text="PType" Value="PType">
        <Node Text="12" Value="12" />
      </Node>
      <Node Text="SType" Value="SType">
        <Node Text="2" Value="2" />
      </Node>
    </Node>
    <Node Text="12YP" Value="12YP">
      <Node Text="PType" Value="PType">
        <Node Text="12" Value="12" />
      </Node>
      <Node Text="SType" Value="SType">
        <Node Text="1" Value="1" />
      </Node>
    </Node>
  </Node>
</Nodes>

我可用的参数是用于 PType 节点和 SType 节点,现在根据它们的值我需要获取父节点属性值。

Example:

Params: {PType:12}, {SType:2} should give me 12YD as a result.  
Params: {PType:12}, {SType:1} should give me 12YP as a result.

即使使用 PredicateBuilder,我也尝试了不同的解决方案,但没有成功。任何帮助将不胜感激。

这是我使用 LinqPad 的最新代码。

void Main()
{
    var xml = XElement.Load (@"C:\map.xml");

    string value = "{PType:12},{SType:1}";
    string[] mapReqValues = value.Split(',');

    var predicate = PredicateBuilder.False<XElement>();
    foreach (string r in mapReqValues)
    {
        var m = Regex.Match(r, @"{([^}]+)}").Groups[1].Value.Split(':');
        predicate = predicate.Or(p => p.Attribute("Value").Value == m[0] && 
            p.Descendants().Attributes("Value").FirstOrDefault().Value == m[1]);

    }

    var result = xml.Descendants().AsQueryable().Where(predicate);
    result.Dump();
}

【问题讨论】:

    标签: c# linq linq-to-xml predicatebuilder


    【解决方案1】:
    XDocument xDoc = XDocument.Load(new StringReader(xml));    
    
    var Tuples = xDoc.Descendants("Node").Where(n => n.Attribute("Text").Value == "PType")
                .Join(
                    xDoc.Descendants("Node").Where(n => n.Attribute("Text").Value == "SType"),
                    n1 => n1.Parent,
                    n2 => n2.Parent,
                    (n1, n2) => new
                    {
                        ParentsValue = n1.Parent.Attribute("Text").Value,
                        PValue = n1.Element("Node").Attribute("Text").Value,
                        SValue = n2.Element("Node").Attribute("Text").Value
                    }
                );
    
    
    var result = Tuples.Where(n => n.PValue == "12" && n.SValue == "1")
                       .Select(n => n.ParentsValue)
                       .ToArray();
    

    【讨论】:

    • 加入!当然哇,这几乎要了我的命。谢谢,非常感谢您的帮助。
    【解决方案2】:

    在处理 XML XPath 是你的朋友...

    对于 PType 12,Stype 1

    var result = xml.XPathSelectElements(@"//Node[Node[@Value='PType']/Node[@Value='12'] and Node[@Value='SType']/Node[@Value='1']]");
    

    这有点拗口……

    //Node
    

    树中任意位置的每个节点

    [Node[@Value='PType']
    

    有一个类型为 Node 的子节点,其属性 Value 的值为 (!) PType

    /Node[@Value='12']
    

    它有一个 Node 类型的子节点,其 Value 属性的值为 12

    还有所有的东西去SType 1

    您可以使用 XPath 过滤掉 XML 中的内容,它可以让您搜索与某个模式匹配的后代——这是它的目标。

    因此,如果您将上面的字符串替换为 string.format,那么您将离开并运行...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-25
      • 1970-01-01
      相关资源
      最近更新 更多