Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 删除XML中的重复元素_C#_Xml - Fatal编程技术网

C# 删除XML中的重复元素

C# 删除XML中的重复元素,c#,xml,C#,Xml,我的项目需要将输入XML文件转换为DataTable的功能。 我使用下面的代码来实现这一点 DataSet ds = new DataSet(); ds.Locale = CultureInfo.InvariantCulture; dataSourceFileStream.Seek(0, SeekOrigin.Begin); ds.ReadXml(dataSourceFileStream); dt = ds.Tables[0]; 除非输入XML有重复的元素,例如,如果XML文件如下:

我的项目需要将输入XML文件转换为DataTable的功能。 我使用下面的代码来实现这一点

 DataSet ds = new DataSet();
 ds.Locale = CultureInfo.InvariantCulture;
 dataSourceFileStream.Seek(0, SeekOrigin.Begin);
 ds.ReadXml(dataSourceFileStream);
 dt = ds.Tables[0];
除非输入XML有重复的元素,例如,如果XML文件如下:

<?xml version="1.0" encoding="iso-8859-1"?>
<DocumentElement>
 <data>
   <DATE>27 September 2013</DATE>
   <SCHEME>Test Scheme Name</SCHEME>
   <NAME>Mr John</NAME>
   <SCHEME>Test Scheme Name</SCHEME>
  <TYPE>1</TYPE>
 </data>
</DocumentElement>

2013年9月27日
测试方案名称
约翰先生
测试方案名称
1.
如上所示,元素方案出现两次。当这种XML文件出现时
ds.ReadXml(dataSourceFileStream)无法返回正确的数据表


有没有更好的方法来处理这个问题?

看起来您必须首先修复XML。您可以通过使用XDocument和关联类来实现这一点。但首先需要创建一个EqualityComparer,它根据两个元素的名称对它们进行比较:

    public class MyEqualityComparer : IEqualityComparer<XElement>
    {
        public bool Equals(XElement x, XElement y)
        {
            return x.Name == y.Name;
        }

        public int GetHashCode(XElement obj)
        {
            return obj.Name.GetHashCode();
        }
    }

这将是解决你问题的快速方法。但是我强烈建议鼓励数据提供者修复XML,好的。正如我在前面的评论中所述,您可以创建自己的XmlTextReader,它可以修补/忽略某些元素。这个想法是,这个读者检查他是否已经阅读了相同深度的元素。如果是这种情况,则前进到结束元素

    class MyXmlReaderPatcher : XmlTextReader
    {
        private readonly HashSet<string> _currentNodeElementNames = new HashSet<string>();

        public MyXmlReaderPatcher(TextReader reader) : base(reader)
        { }

        public override bool Read()
        {
            var result = base.Read();

            if (this.Depth == 1)
            {
                _currentNodeElementNames.Clear();
            }
            else if (this.Depth==2 && this.NodeType == XmlNodeType.Element)
            {
                if (_currentNodeElementNames.Contains(this.Name))
                {
                    var name = this.Name;

                    do {
                        result = base.Read();
                        if (result == false)
                            return false;
                    } while (this.NodeType != XmlNodeType.EndElement && this.Name != name);

                    result = this.Read();
                }
                else
                {
                    _currentNodeElementNames.Add(this.Name);
                }
            }

            return result;
        }
    }

尝试使用ReadXml(stream,XmlReadMode.IgnoreSchema.You想要将任何输入XML文件转换为DataTable吗?如果是,那么这不是个好主意,因为XML包含层次结构data@Carra我试过了。它也不起作用。@lazyberezovsky,我们没有转换任何类型的xml文件,我们已经接受了一个只有一个层次结构的文件可以完全有效地转换为行和列值。谢谢,但是有没有一种方法可以使用LINQ实现相同的转换?这是什么意思?这意味着一个一行程序可以完成所有需要的工作?是的,有点像内联LINQ语句,只是好奇而已。无论如何,用户名::)基本逻辑在foreach循环中。所有其他的东西都用于将字符串/流放入XDocument,反之亦然。另一种选择是编写自定义XmlTextReader并跳过重复的元素。谢谢,伙计,由于时间限制,我已经按照此答案进行了编码。谢谢。谢谢你的回答。
    class MyXmlReaderPatcher : XmlTextReader
    {
        private readonly HashSet<string> _currentNodeElementNames = new HashSet<string>();

        public MyXmlReaderPatcher(TextReader reader) : base(reader)
        { }

        public override bool Read()
        {
            var result = base.Read();

            if (this.Depth == 1)
            {
                _currentNodeElementNames.Clear();
            }
            else if (this.Depth==2 && this.NodeType == XmlNodeType.Element)
            {
                if (_currentNodeElementNames.Contains(this.Name))
                {
                    var name = this.Name;

                    do {
                        result = base.Read();
                        if (result == false)
                            return false;
                    } while (this.NodeType != XmlNodeType.EndElement && this.Name != name);

                    result = this.Read();
                }
                else
                {
                    _currentNodeElementNames.Add(this.Name);
                }
            }

            return result;
        }
    }
        var myReader = new MyXmlReaderPatcher(dataSourceFileStream);

        var ds = new DataSet();
        ds.Locale = CultureInfo.InvariantCulture;
        var mode = ds.ReadXml(myReader);
        var dt = ds.Tables[0];