Linq to XML Получить значение атрибута родительского элемента, запросив его потомки - PullRequest
1 голос
/ 20 марта 2012

Я пытаюсь построить Linq to XML Query, но пока не нашел реального решения.

Вот мой 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();
}

Ответы [ 2 ]

2 голосов
/ 20 марта 2012

Имея дело с 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

Вы можете отфильтровать черт изXML с XPath, и он позволит вам искать потомков, которые соответствуют шаблону - это то, для чего он предназначен.

Так что если вы замените приведенную выше строку на string.format, то у вас все будет в порядке ...

2 голосов
/ 20 марта 2012
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();
...