我有一个复杂的案例:我有三个XML文件,我需要同时阅读并根据匹配得到结果。下面是一个工作(但假的)示例,几乎与我正在做的相似。
例如,我有两个xml文件,两者都很相似,但在标签和属性方面,但具有不同的内容(语言)。我正在同时阅读这两种语言,就像在C#文件中的代码一样:
XElement x1 = XElement.Load (@"abc.xml");
XElement x2 = XElement.Load (@"xyz.xml");
var ch = from var1 in x1.Elements("language1")
where var1.Attribute("index").Value == "1"
from var2 in x2.Elements("language2")
where var2.Attribute("index").Value == var1.Attribute("index").Value
select dictChapter as new
{
sentenceNumber = var1.Attribute("index").Value,
SentenceInLanguage1 = var1.Attribute("text").Value,
SentenceInLanguage2 = var2.Attribute("text").Value,
};
ListBox.DataContext = ch;
这里的问题是,x1包含1000个句子,所以x2。上面的逻辑工作就像一个嵌套循环,这会大大减慢处理速度。它就像
一样x1.1 -> x2.1:1000
x1.2 -> x2.1:1000
或
for i in x1
for j in x2
有没有更好更有效的方法从x1和x2中选择句子,其中x1的句子id等于x2的句子id?
答案 0 :(得分:1)
据我所知,你想要的,
您可以使用join
来执行此操作。
以下是一个很好的示例链接LINQ to XML : Join Xml Data (Wriju's BLOG)
......或者沿着这些方向......
var root = (from var1 in x1.Elements("language1")
join var2 in x2.Elements("language2") on (string)var1.Attribute("index") equals (string)var2.Attribute("index")
select new
{
SentenceNumber = (string)var1.Attribute("index"),
SentenceInLanguage1 = (string)var1.Element("text"),
SentenceInLanguage2 = (string)var2.Element("text")
});
答案 1 :(得分:1)
在Linq中,以下陈述是等效的,并将提供相同的结果:
from i1 in items1
from i2 in items2
where i1 == i2
和
from i1 in items1
join i2 in items2 on i1 equals i2
它们甚至会被翻译成相同的SQL(使用Linq to SQL)。对于两种情况下的MS SQL,结果SQL将包含join子句(这就是为什么在查询数据库时不需要使用灵活性较低的join
。
然而,对于 Linq to Objects 和 Linq to XML ,两者都将以不同的方式执行。首先会导致嵌套循环,第二次不会。
所以你只需要改变你的实现以使用join
作为@NSGaga的建议。
另一项优化是添加.ToList()
:
ListBox.DataContext = ch;
我不确定数据绑定,但由于linq的自然性质,您的表达式可能会被重复评估多次。
答案 2 :(得分:0)
轻松!只需按顺序浏览每个文件。在第一遍:创建sentenceNumber > SentenceInlanguage1
。
在第二遍中,按照您显示的代码创建可枚举,粘贴SentenceInLanguage1
变量第一遍的数据。
如果您希望同时浏览这两个内容,只需获取一个枚举器(GetEnumerator
)并浏览一个普通的while
循环,然后转到下一个XElement
循环体末端的枚举器。