繁体   English   中英

c#联接XML文件使用Linq DefaultIfEmpty()产生重复项

[英]c# join XML files produce duplicates using Linq DefaultIfEmpty()

我正在尝试对两个XML文档使用leftOuterJoin,但是我当前使用的方式似乎从fileone返回了一些奇怪的重复部分(在下面的代码中进行了解释)。 我已经尝试了很多方法,但是却不知道该怎么做。 有人可以帮助解决这个问题吗? 提前谢谢了!

文件名:

<fileone>

    <Book BookID="dog"> Dog </Book>

    <Book BookID="cat"> Cat </Book>

</fileone>

文件二:

<filetwo>

       <Edition BID="cat" OrderID="100"> about cat</Edition>

       <Edition BID="cat" OrderID="200">more about cat</Edition>

</RightSeq>

我正在寻找的是(bookID = BID上的左外部联接):

<item>
   <Book BookID="cat"> Dog </Book>
</item>
<item>
    <Book BookID="cat"> Cat </Book>
    <Edition BID="cat" OrderID="100"> about cat</Edition>
</item>
<item>
    <Book BookID="cat"> Cat </Book>
    <Edition BID="cat" OrderID="200"> more cat</Edition>
</item>

我的(错误的)代码:

      var result = from a in fileone.Descendants()
      join b in secondxdoc.Descendants()
     on (string)a.Attribute("BookID") equal (string)b.Attribute("BID") into inners
      from ele in inners.DefaultIfEmpty()

      select new XElement("item", new XElement(a), ele == null ? null : new XElement(ele));
        var output = new XElement("LeftOuterJoin", result);         
    }

当前错误的结果:

<item>
   <fileone>  
       <Book BookID="dog"> Dog </Book> // this entire <fileone> bit is unwanted
       <Book BookID="cat"> Cat </Book>  //I don't know what I've done wrong
   </fileone> 
</item>
    <item>
   <Book BookID="cat"> Dog </Book>
</item>
<item>
    <Book BookID="cat"> Cat </Book>
    <Edition BID="cat" OrderID="100"> about cat</Edition>
</item>
<item>
    <Book BookID="cat"> Cat </Book>
    <Edition BID="cat" OrderID="200"> more cat</Edition>
</item>  

多余的第一个<item>元素是将根元素<fileone>与第二个文件的后代结合在一起的结果。 如果要跳过根元素,请将fileone.Descendants()替换为fileone.Root.Descendants()

var result = from a in fileone.Root.Descendants()
             join b in secondxdoc.Descendants()
                on (string)a.Attribute("BookID") equal (string)b.Attribute("BID") into inners
             from ele in inners.DefaultIfEmpty()
             select new XElement("item", a, ele);
var output = new XElement("LeftOuterJoin", result);

Dotnetfiddle Demo

我没有使用传统的linq就得到了结果。 如果fileone在filetwo中没有匹配的项,则联接将不会给出结果。

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml; using System.Xml.Linq; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { string input1 = "<fileone>" + "<Book BookID=\\"dog\\"> Dog </Book>" + "<Book BookID=\\"cat\\"> Cat </Book>" + "</fileone>"; XDocument fileone = XDocument.Parse(input1); string input2 = "<filetwo>" + "<Edition BID=\\"cat\\" OrderID=\\"100\\"> about cat</Edition>" + "<Edition BID=\\"cat\\" OrderID=\\"200\\">more about cat</Edition>" + "</filetwo>"; XDocument secondxdoc = XDocument.Parse(input2); //<item> // <Book BookID="cat"> Dog </Book> //</item> //<item> // <Book BookID="cat"> Cat </Book> // <Edition BID="cat" OrderID="100"> about cat</Edition> //</item> //<item> // <Book BookID="cat"> Cat </Book> // <Edition BID="cat" OrderID="200"> more cat</Edition> //</item> XElement output = new XElement("Root"); foreach (XElement item in fileone.Descendants("Book")) { string bookId = item.Attribute("BookID").Value; List<XElement> bookTwoItems = secondxdoc.Descendants("Edition").Where(x => x.Attribute("BID").Value == bookId).ToList(); if (bookTwoItems.Count == 0) { XElement newItem = new XElement("item"); output.Add(newItem); newItem.Add(item); } else { foreach (XElement bookTwoItem in bookTwoItems) { XElement newItem = new XElement("item"); output.Add(newItem); newItem.Add(item); newItem.Add(bookTwoItem); } } } } } }​ 

与左外部联接一起使用

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input1 =
               "<fileone>" +
                   "<Book BookID=\"dog\"> Dog </Book>" +
                   "<Book BookID=\"cat\"> Cat </Book>" +
               "</fileone>";
            XDocument fileone = XDocument.Parse(input1);

            string input2 =
               "<filetwo>" +
                      "<Edition BID=\"cat\" OrderID=\"100\"> about cat</Edition>" +
                      "<Edition BID=\"cat\" OrderID=\"200\">more about cat</Edition>" +
               "</filetwo>";
            XDocument secondxdoc = XDocument.Parse(input2);

            //<item>
            //   <Book BookID="cat"> Dog </Book>
            //</item>
            //<item>
            //    <Book BookID="cat"> Cat </Book>
            //    <Edition BID="cat" OrderID="100"> about cat</Edition>
            //</item>
            //<item>
            //    <Book BookID="cat"> Cat </Book>
            //    <Edition BID="cat" OrderID="200"> more cat</Edition>
            //</item>
            var results = (from one in fileone.Descendants("Book")
                           join two in secondxdoc.Descendants("Edition") on one.Attribute("BookID").Value equals two.Attribute("BID").Value into inners
                           from two in inners.DefaultIfEmpty()
                           select new { fileone = one, filetwo = two == null ? null : two }).ToList(); 
            XElement output = new XElement("Root");
            foreach (var item in results)
            {
                XElement newItem = new XElement("item");
                output.Add(newItem);
                newItem.Add(item.fileone);
                if (item.filetwo  != null)
                {
                        newItem.Add(item.filetwo);
                }

            }

        }
    }
}
​

还是这个方法

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string input1 =
               "<fileone>" +
                   "<Book BookID=\"dog\"> Dog </Book>" +
                   "<Book BookID=\"cat\"> Cat </Book>" +
               "</fileone>";
            XDocument fileone = XDocument.Parse(input1);

            string input2 =
               "<filetwo>" +
                      "<Edition BID=\"cat\" OrderID=\"100\"> about cat</Edition>" +
                      "<Edition BID=\"cat\" OrderID=\"200\">more about cat</Edition>" +
               "</filetwo>";
            XDocument secondxdoc = XDocument.Parse(input2);

            //<item>
            //   <Book BookID="cat"> Dog </Book>
            //</item>
            //<item>
            //    <Book BookID="cat"> Cat </Book>
            //    <Edition BID="cat" OrderID="100"> about cat</Edition>
            //</item>
            //<item>
            //    <Book BookID="cat"> Cat </Book>
            //    <Edition BID="cat" OrderID="200"> more cat</Edition>
            //</item>
            XElement output = new XElement("Root");
            var results = (from one in fileone.Descendants("Book")
                           join two in secondxdoc.Descendants("Edition") on one.Attribute("BookID").Value equals two.Attribute("BID").Value into inners
                           from two in inners.DefaultIfEmpty()
                           select new { fileone = one, filetwo = two == null ? null : two })
                           .Select(x => x.filetwo == null ? new XElement("item", x.fileone) : new XElement("item", new object[] { x.fileone, x.filetwo }));
            foreach (var item in results)
            {
                output.Add(item);
            }
        }
    }
}
​

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM