我有这个XML字符串“booms”:
<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更改为过滤掉满足某些条件的繁荣?例如,如何过滤掉地址中包含“新”的繁荣?在这种情况下,这将给出字符串:
name: John
address: New York City
但代码不应仅限于“包含”过滤器。
答案 0 :(得分:1)
如果条件限制为相等。
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);
如果它不限于等于(包含,等于,&lt;,&gt;),则必须创建一个代表条件的结构。
// 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);
答案 1 :(得分:1)
我强烈要输入:
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!*/);
答案 2 :(得分:0)
没有测试过,但试试这个:
//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);
将您的测试替换为x ...