向此LINQ to XML代码添加条件/筛选器

本文关键字:条件 筛选 添加 代码 LINQ to XML 向此 | 更新日期: 2023-09-27 18:24:36

我有一个"booms"的XML字符串:

<booms>
  <boom>
    <name>John</name>
    <address>New York City</address>
  </boom>
  <boom>
    <name>Daniel</name>
    <address>Los Angeles</address>
  </boom>
  <boom>
    <name>Joe</name>
    <address>Chicago</address>
  </boom>
</booms>

我还有这个LINQ C#代码

//string xmlString = ...;
XDocument document = XDocument.Load(new StringReader(xmlString));
var booms = from boomElement in document.Descendants("boom")
            let boolChildren = (from boomElementChild in boomElement.Elements()
                                select String.Format("{0}: {1}",
                                                     boomElementChild.Name.LocalName,
                                                     boomElementChild.Value))
            select String.Join(Environment.NewLine, boolChildren);
var result = String.Join(Environment.NewLine + Environment.NewLine, booms);

将XML转换为以下字符串:

name: John
address: New York City
name: Daniel
address: Los Angeles
name: Joe
address: Chicago

问题:

如何将LINQ更改为过滤出满足某些条件的动臂?例如,如何筛选出地址包含"New"的吊杆?在这种情况下,这将给出字符串:

name: John
address: New York City

不过,代码不应仅限于"包含"筛选器。

向此LINQ to XML代码添加条件/筛选器

如果条件限制为相等。

Dictionary<string, string> conditions = new Dictionary<string, string> { { "name", "John" } };
XDocument document = XDocument.Load(new StringReader(xmlString));
var booms = from boomElement in document.Descendants("boom")
            where conditions.All(condition => (string)boomElement.Element(condition.Key) == condition.Value)  // Where is used to filter the result
            let boomChildren = (from boomElementChild in boomElement.Elements()
                                select String.Format("{0}: {1}",
                                                     boomElementChild.Name.LocalName,
                                                     boomElementChild.Value))
            select String.Join(Environment.NewLine, boomChildren);
var result = String.Join(Environment.NewLine + Environment.NewLine, booms);

如果它不限于等于(contain,equal,<,>),则必须创建一个表示条件的结构。

// I've made Condition an abstract class to super any kind of condition.
// Just derive this class with the condition you want (And, Or, Equal, <=, IsNumber, ...)
public abstract class Condition
{
    // A condition is defined by this method. Because a condition is basically: "Does the specified value satisfy the condition?"
    public abstract bool Satisfy(string valueToTest);  
}
// This is the first example of condition.
// I wanted to make the condition immutable (readonly) not to be able to change them.
// So, all parameters of the condition are set during the construction.
public sealed class EqualCondition : Condition
{
    private readonly string value;
    public string Value { get { return value; } }
    public EqualCondition(string value)
    {
        this.value = value;
    }
    public override bool Satisfy(string valueToTest)
    {
        return value == valueToTest;  // Equals condition...
    }
}
public sealed class ContainCondition : Condition
{
    private readonly string value;
    public string Value { get { return value; } }
    public ContainCondition(string value)
    {
        this.value = value;
    }
    public override bool Satisfy(string valueToTest)
    {
        return valueToTest.Contains(valueToTest);  // Contains condition
    }
}
// The dictionary is used to list the conditions applied to each element.
Dictionary<string, Condition> conditions = new Dictionary<string, Condition> { { "name", new EqualCondition("John") } };  
XDocument document = XDocument.Load("test.xml");
var booms = from boomElement in document.Descendants("boom")
            // The next line check where all conditions are satisfied for the corresponding elements
            where conditions.All(condition => condition.Value.Satisfy((string)boomElement.Element(condition.Key)))
            let boomChildren = (from boomElementChild in boomElement.Elements()
                                select String.Format("{0}: {1}",
                                                        boomElementChild.Name.LocalName,
                                                        boomElementChild.Value))
            select String.Join(Environment.NewLine, boomChildren);
var result = String.Join(Environment.NewLine + Environment.NewLine, booms);

我会强烈键入以下内容:

public class Boom
{
    string Name { get; set; }
    string Address { get; set; }
    public override string ToString()
    {
        return string.Format("Name: {0}{1}Address: {2}, Name, Environment.NewLine, Address);
    }
}

因此,您的查询更改为:

XDocument document = XDocument.Load(new StringReader(xmlString));
var booms = 
    document.Descendants("boom")
            .Select(x => new Boom { Name = x.Element("name").Value,
                                    Address = x.Element("address").Value })
            .Where(b => /*filter here!*/);

还没有测试过,但尝试一下:

//string xmlString = ...;
XDocument document = XDocument.Load(new StringReader(xmlString));
var booms = from boomElement in document.Descendants("boom").Where(x => true)
            let boolChildren = (from boomElementChild in boomElement.Elements()
                                select String.Format("{0}: {1}",
                                                     boomElementChild.Name.LocalName,
                                                     boomElementChild.Value))
            select String.Join(Environment.NewLine, boolChildren);
var result = String.Join(Environment.NewLine + Environment.NewLine, booms);

将true替换为您在x上的测试…