开发者

LINQ to XML equivalent of XPath

开发者 https://www.devze.com 2023-02-11 04:30 出处:网络
I have code which 开发者_Go百科parses XML that looks like this: <custom_fields> <custom_field>

I have code which 开发者_Go百科parses XML that looks like this:

<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...

I want to find the element called custom_field which has a child element called column_name with a certain value (for example bar), and then find that child's sibling called column_value and get its value. Right now I use XPath on an XMlDocument to do this:

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

Where key is the name of the field I am looking for.

But I want to do this using the new LINQ to XML syntax on an XDocument. My thinking is that I will move much of my old-style XPath parsing to the LINQ methods. Maybe it's not a good idea, but this is a case where if I can get it to work, then I believe I will have a much better understanding of LINQ in general, and will be able to clean up a lot of complex code.


You can always use XPath within LINQ to XML. Just include the System.Xml.XPath namespace.

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

Otherwise for the equivalent LINQ to XML query:

var columnValue = doc.Descendants("custom_fields")
    .Elements("custom_field")
    .Where(cf => (string)cf.Element("column_name") == key) // assuming `key` is a string
    .Elements("column_value")
    .SingleOrDefault();


Your XQuery expression

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

selects all custom_field elements in custom_fields elements where the value of the column_key child element equals "key". You expect a single element to be returned and select the value of the column_value child element.

You can express this using LINQ to XML as follows:

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


I want to find the element called custom_field which has a child element called column_name with a certain value (for example "bar", and then find that child's sibling called column_value and get its value.

Use:

/custom_fields/custom_field[column_name = 'bar']/column_value
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号