如何以有效的方式同时读取两个XML文件

时间:2012-04-17 14:45:19

标签: c# .net performance linq linq-to-xml

我有一个复杂的案例:我有三个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?

3 个答案:

答案 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循环体末端的枚举器。