首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >比较两个XML文件&在C#中使用XMLDiff生成第三个XML文件

比较两个XML文件&在C#中使用XMLDiff生成第三个XML文件
EN

Stack Overflow用户
提问于 2011-01-04 10:37:39
回答 1查看 48.8K关注 0票数 19

我正在尝试编写一个简单的算法来读取两个XML文件,它们具有完全相同的节点和结构,但子节点中的数据不一定相同,顺序也不相同。如何使用微软的XML Diff .DLL创建一个简单的实现来创建第三个临时XML,这是前两个XML之间的区别?

MSDN上的XML Diff:

XML Diff and Patch Tool

XML Diff and Patch GUI Tool

要比较的两个不同XML文件的示例XML代码:

<?xml version="1.0" encoding="utf-8" ?> 
<Stats Date="2011-01-01">
 <Player Rank="1">
  <Name>Sidney Crosby</Name> 
  <Team>PIT</Team> 
  <Pos>C</Pos> 
  <GP>39</GP> 
  <G>32</G> 
  <A>33</A> 
  <PlusMinus>20</PlusMinus> 
  <PIM>29</PIM> 
 </Player>
</Stats>

<?xml version="1.0" encoding="utf-8" ?> 
<Stats Date="2011-01-10">
 <Player Rank="1">
  <Name>Sidney Crosby</Name> 
  <Team>PIT</Team> 
  <Pos>C</Pos> 
  <GP>42</GP> 
  <G>35</G> 
  <A>34</A> 
  <PlusMinus>22</PlusMinus> 
  <PIM>30</PIM> 
 </Player>
</Stats>

想要的结果(两者之间的差异)

<?xml version="1.0" encoding="utf-8" ?> 
<Stats Date="2011-01-10">
 <Player Rank="1">
  <Name>Sidney Crosby</Name> 
  <Team>PIT</Team> 
  <Pos>C</Pos> 
  <GP>3</GP> 
  <G>3</G> 
  <A>1</A> 
  <PlusMinus>2</PlusMinus> 
  <PIM>1</PIM> 
 </Player>
</Stats>

在本例中,我可能会使用XSLT将生成的XML“差异”文件转换为排序的HTML文件,但我还没有做到这一点。我所要做的就是在第三个XML文件中显示每个节点从"GP“子节点开始的每个数值的差异。

到目前为止我所拥有的C#代码:

private void CompareXml(string file1, string file2)
{

    XmlReader reader1 = XmlReader.Create(new StringReader(file1));
    XmlReader reader2 = XmlReader.Create(new StringReader(file2));

    string diffFile = StatsFile.XmlDiffFilename;
    StringBuilder differenceStringBuilder = new StringBuilder();

    FileStream fs = new FileStream(diffFile, FileMode.Create);
    XmlWriter diffGramWriter = XmlWriter.Create(fs);

    XmlDiff xmldiff = new XmlDiff(XmlDiffOptions.IgnoreChildOrder |
                            XmlDiffOptions.IgnoreNamespaces |
                            XmlDiffOptions.IgnorePrefixes);
    bool bIdentical = xmldiff.Compare(file1, file2, false, diffGramWriter);

    diffGramWriter.Close();

    // cleaning up after we are done with the xml diff file
    File.Delete(diffFile);
}

这就是我到目前为止所知道的,但是结果是垃圾...请注意,对于每个"Player“节点,前三个孩子不必进行比较……我如何实现这一点?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-01-05 16:01:19

好吧..。最后,我选择了一个纯C#解决方案来比较这两个XML文件,而不使用XML Diff/Patch .dll,甚至不需要使用XSL转换。在下一步中,我将需要XSL转换,以便将Xml转换为超文本标记语言,以便于查看,但我已经提出了一种只使用System.Xml和System.Xml.XPath的算法。

下面是我的算法:

private void CompareXml(string file1, string file2)
{
    // Load the documents
    XmlDocument docXml1 = new XmlDocument();
    docXml1.Load(file1);
    XmlDocument docXml2 = new XmlDocument();
    docXml2.Load(file2);


    // Get a list of all player nodes
    XmlNodeList nodes1 = docXml1.SelectNodes("/Stats/Player");
    XmlNodeList nodes2 = docXml2.SelectNodes("/Stats/Player");

    // Define a single node
    XmlNode node1;
    XmlNode node2;

    // Get the root Xml element
    XmlElement root1 = docXml1.DocumentElement;
    XmlElement root2 = docXml2.DocumentElement;

    // Get a list of all player names
    XmlNodeList nameList1 = root1.GetElementsByTagName("Name");
    XmlNodeList nameList2 = root2.GetElementsByTagName("Name");

    // Get a list of all teams
    XmlNodeList teamList1 = root1.GetElementsByTagName("Team");
    XmlNodeList teamList2 = root2.GetElementsByTagName("Team");

    // Create an XmlWriterSettings object with the correct options. 
    XmlWriter writer = null;
    XmlWriterSettings settings = new XmlWriterSettings();
    settings.Indent = true;
    settings.IndentChars = ("  ");
    settings.OmitXmlDeclaration = false;

    // Create the XmlWriter object and write some content.
    writer = XmlWriter.Create(StatsFile.XmlDiffFilename, settings);
    writer.WriteStartElement("StatsDiff");


    // The compare algorithm
    bool match = false;
    int j = 0;

    try 
    {
        // the list has 500 players
        for (int i = 0; i < 500; i++)
        {
            while (j < 500 && match == false)
            {
                // There is a match if the player name and team are the same in both lists
                if (nameList1.Item(i).InnerText == nameList2.Item(j).InnerText)
                {
                    if (teamList1.Item(i).InnerText == teamList2.Item(j).InnerText)
                    {
                        match = true;
                        node1 = nodes1.Item(i);
                        node2 = nodes2.Item(j);
                        // Call to the calculator and Xml writer
                        this.CalculateDifferential(node1, node2, writer);
                        j = 0;
                    }
                }
                else
                {
                    j++;
                }
            }
            match = false;

        }
        // end Xml document
        writer.WriteEndElement();
        writer.Flush();
    }
    finally
    {
        if (writer != null)
            writer.Close();
    }
}

XML结果:

<?xml version="1.0" encoding="utf-8"?>
<StatsDiff>    
  <Player Rank="1">
    <Name>Sidney Crosby</Name>
    <Team>PIT</Team>
    <Pos>C</Pos>
    <GP>0</GP>
    <G>0</G>
    <A>0</A>
    <Points>0</Points>
    <PlusMinus>0</PlusMinus>
    <PIM>0</PIM>
    <PP>0</PP>
    <SH>0</SH>
    <GW>0</GW>
    <OT>0</OT>
    <Shots>0</Shots>
    <ShotPctg>0</ShotPctg>
    <ShiftsPerGame>0</ShiftsPerGame>
    <FOWinPctg>0</FOWinPctg>
  </Player>

  <Player Rank="2">
    <Name>Steven Stamkos</Name>
    <Team>TBL</Team>
    <Pos>C</Pos>
    <GP>1</GP>
    <G>0</G>
    <A>0</A>
    <Points>0</Points>
    <PlusMinus>0</PlusMinus>
    <PIM>2</PIM>
    <PP>0</PP>
    <SH>0</SH>
    <GW>0</GW>
    <OT>0</OT>
    <Shots>4</Shots>
    <ShotPctg>-0,6000004</ShotPctg>
    <ShiftsPerGame>-0,09999847</ShiftsPerGame>
    <FOWinPctg>0,09999847</FOWinPctg>
  </Player>
[...]
</StatsDiff>

我已经展示了CalculateDifferential()方法的实现,它相当神秘,但它是快速和有效的。这样,我就可以在不使用任何其他引用的情况下获得所需的结果,而不必使用XSL...

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4590214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档