LINQ to XML эквивалент XPath - PullRequest
       32

LINQ to XML эквивалент XPath

3 голосов
/ 19 февраля 2011

У меня есть код, который анализирует XML, который выглядит следующим образом:

<custom_fields>
  <custom_field>
      <column_name>foo</column_name>
    <column_value>0</column_value>
  <description>Submitted</description>
    <data_type>BOOLEAN</data_type>
    <length>0</length>
    <decimal>0</decimal>
  </custom_field>
  <custom_field>
    <column_name>bar</column_name>
    <column_value>0</column_value>
    <description>Validated</description>
    <data_type>BOOLEAN</data_type>
    <length>0</length>
    <decimal>0</decimal>
  </custom_field>
</custom_fields>
... more <custom_field> elements...

Я хочу найти элемент с именем custom_field, у которого есть дочерний элемент с именем column_name с определенным значением (например, bar), а затем найти брата этого дочернего элемента с именем column_value и получить его значение. Прямо сейчас я использую XPath на XMlDocument, чтобы сделать это:

string path = "//custom_fields/custom_field[column_name='" + key + "']";
XmlNode xNode = doc.SelectSingleNode(path);
if (xNode != null)
{
    XmlNode v = xNode.SelectSingleNode("column_value");
    val.SetValue(v.InnerText);
}

Где key - это название поля, которое я ищу.

Но я хочу сделать это, используя новый синтаксис LINQ to XML на XDocument. Я думаю, что большую часть своего анализа XPath старого стиля перенесу на методы LINQ. Возможно, это не очень хорошая идея, но это тот случай, когда, если я смогу заставить его работать, то, я думаю, у меня будет намного лучшее понимание LINQ в целом, и я смогу очистить много сложного кода.

Ответы [ 3 ]

4 голосов
/ 19 февраля 2011

Вы всегда можете использовать XPath в LINQ to XML.Просто включите пространство имен System.Xml.XPath.

var xpath = String.Format("//custom_fields/custom_field[column_name='{0}']/column_value", key);
var custom_field = doc.XPathSelectElement(xpath);
if (custom_field != null)
{
    val.SetValue((int)custom_field);
}

В противном случае для эквивалентного запроса LINQ to XML:

var custom_field = doc.Descendants("custom_fields")
                      .Elements("custom_field")
                      .Where(cf => cf.Element("column_name").Value == key) // assuming `key` is a string
                      .Elements("column_value")
                      .SingleOrDefault();
1 голос
/ 19 февраля 2011

Я хочу найти элемент с именем custom_field, у которого есть дочерний элемент с именем column_name с определенным значением (например, «bar»), а затем найти брата этого дочернего элемента column_value и получить его значение.*

Использование:

/custom_fields/custom_field[column_name = 'bar']/column_value
1 голос
/ 19 февраля 2011

Ваше выражение XQuery

//custom_fields/custom_field[column_name='key']

выбирает все элементы custom_field в custom_fields элементах, где значение дочернего элемента column_key равно "key".Вы ожидаете возврата одного элемента и выбираете значение дочернего элемента column_value.

Вы можете выразить это с помощью LINQ to XML следующим образом:

var doc = XDocument.Load(...);

var query = from fields in doc.Descendants("custom_fields")
            from field in fields.Elements("custom_field")
            where (string)field.Element("column_name") == "key"
            select (int)field.Element("column_value");

int result = query.Single();
...