0

我有两个 XML 文件需要比较差异,XML 非常简单:

文件 1:

<?xml version="1.0" encoding="utf-8"?>
<Feeds zone="my zone">
  <Feed name="attribDump.json">ac1f07edc491a3d237cdfb1a17fc4551</Feed>
  <Feed name="focus_GroupsKV.txt">0f9e0a14a4ffce6ff5065b6e088c1f84</Feed>
  <Feed name="NAM_FORMATTED.csv">9e875496cdb072b5e54318d51295fdba</Feed>
  <Feed name="BNP\activityTitles.txt">2d27c0f19b71b4b411bcb00011d3f8b0</Feed>
</Feeds>

和文件 2:

<?xml version="1.0" encoding="utf-8"?>
<FeedsRequest version="1">
<Feeds zone="my zone">
  <Feed name="attribDump.json">ac1f07edc491a3d237cdfb1a17fc4551</Feed>
  <Feed name="focus_GroupsKV.txt">0f9e0a14a4ffce6ff5065b6e088c1f84</Feed>
  <Feed name="BNP\activityTitles.txt">e54c5b851ee3ff3f43b10d24f2316431</Feed>
</Feeds>
</FeedsRequest>

文件 1 是我们文件共享上文件的清单列表,文件 2 由需要从文件 1 刷新的断开连接的设备使用。我需要进行的检查是 1) 确保文件 1 中的所有提要都是在文件 2 和 2 中)确保找到的所有提要都具有相同的 hashCode(长字符串)。检查完成后,我需要创建一个响应文件,其中包含所有提要的列表,然后在每个提要上指定一个属性,指定 ok(找到并匹配文件)、丢失(未找到文件)、或更新(找到文件但它是旧版本)。

所以基本上结果文件看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<FeedsResponse version="1">
<Feeds zone="my zone">
  <Feed name="attribDump.json" status="ok">ac1f07edc491a3d237cdfb1a17fc4551</Feed>
  <Feed name="focus_GroupsKV.txt" status="ok">0f9e0a14a4ffce6ff5065b6e088c1f84</Feed>
  <Feed name="NAM_FORMATTED.csv" status="missing">afd2c620053ed4f85ab02b4cc5f7a2b2</Feed>
  <Feed name="BNP\activityTitles.txt" status="updated">90805b851ee3ff3f43b10d24f2316431</Feed>

我目前正在做的是遍历文件 1 中的所有文件,然后对照文件 2 检查它们是否存在差异。自从我使用 XML 以来已经有一段时间了,我遇到的问题是如何构建响应文档。

            FileInfo feedList = new FileInfo(_feedList);
        FileInfo feedRequest = new FileInfo(_feedRequest);

        // Load the documents
        XmlDocument feedListXmlDoc = new XmlDocument();
        feedListXmlDoc.Load(_feedList);

        // Load the documents
        XmlDocument feedRequestXmlDoc = new XmlDocument();
        feedRequestXmlDoc.Load(_feedRequest);

        //create response doc
        XmlDocument feedResponseXmlDoc = new XmlDocument();

        // Define a single node
        XmlNode feedListNode;
        XmlNode feedRequestNode;

        // Get the root Xml element
        XmlElement feedListRoot = feedListXmlDoc.DocumentElement;
        XmlElement feedRequestRoot = feedRequestXmlDoc.DocumentElement;

        // Get a list of all player names
        XmlNodeList feedListXml = feedListRoot.GetElementsByTagName("Feed");
        XmlNodeList feedRequestXml = feedRequestRoot.GetElementsByTagName("Feed");

        // 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(_resultPath, settings);
        writer.WriteStartElement("FeedsDiff");

        // The compare algorithm
        bool feedMatch = false;

        int j = 0;

        try 
        {
            // loop through list of current feeds
            for (int i = 0; i < feedListXml.Count; i++)
            {
                feedListNode = feedListXml.Item(i);

                string feedListName = feedListNode.Attributes["name"].Value.ToString();
                string feedListHash = feedListXml.Item(i).InnerText.ToString();

                //check feed request list for a match
                while (j < feedRequestXml.Count && feedMatch == false)
                {
                    feedRequestNode = feedRequestXml.Item(j);
                    string feedRequestName = feedRequestNode.Attributes["name"].Value.ToString();

                    //checks to see if feed names match
                    if (feedListName == feedRequestName)
                    {
                        feedMatch = true;
                        string feedRequestHash = feedRequestXml.Item(j).InnerText.ToString();

                        //since we found the node, we can remove it from the request list
                        XmlNode node = feedRequestNode.ParentNode;
                        node.RemoveChild(feedRequestNode);

                        //checks to see if hash codes match
                        if (feedListHash == feedRequestHash)
                        {
                            //if name and code match, move to the next one
                            feedMatch = true;

                            //add 'status="ok"' attribute to the node
                            //feedResponseXmlDoc.ImportNode(feedRequestNode,false);

                            Debug.WriteLine(feedListName + " name and hash match");

                            j = 0;
                        }
                        else 
                        {

                            feedMatch = true;

                            //feed has been updated since last device sync
                            //need to add status='update' attribute and append file to response
                            Debug.WriteLine(feedListName + " name matched but hash did not");
                        }
                    }
                    else
                    {
                        //names didn't match
                        //add status="missing" to the node
                        j++;
                    }
                }
                feedMatch = false;
            }
            // end Xml document
            writer.WriteEndElement();
            writer.Flush();
        }
        finally
        {
            if (writer != null)
                writer.Close();
        }

现在我正在尝试在循环之前实例化响应文档,然后在找到元素时添加它们,但我很难找到一种简洁的方法来做到这一点。任何帮助表示赞赏。

4

2 回答 2

0

我想到了:

public void CompareXml(string _feedList, string _feedRequest, string _resultPath)
    {
        FileInfo feedList = new FileInfo(_feedList);
        FileInfo feedRequest = new FileInfo(_feedRequest);

        // Load the documents
        XmlDocument feedListXmlDoc = new XmlDocument();
        feedListXmlDoc.Load(_feedList);

        // Load the documents
        XmlDocument feedRequestXmlDoc = new XmlDocument();
        feedRequestXmlDoc.Load(_feedRequest);

        // Define a single node
        XmlNode feedListNode;
        XmlNode feedRequestNode;

        // Get the root Xml element
        XmlElement feedListRoot = feedListXmlDoc.DocumentElement;
        XmlElement feedRequestRoot = feedRequestXmlDoc.DocumentElement;

        // Get a list of feeds for the stored list and the request
        XmlNodeList feedListXml = feedListRoot.GetElementsByTagName("Feed");
        XmlNodeList feedRequestXml = feedRequestRoot.GetElementsByTagName("Feed");

        bool feedLocated = false;
        int j = 0;

        try 
        {
            // loop through list of current feeds
            for (int i = 0; i < feedListXml.Count; i++)
            {
                feedListNode = feedListXml.Item(i);
                //create status attribute
                XmlAttribute attr = feedListXmlDoc.CreateAttribute("status");

                string feedListName = feedListNode.Attributes["name"].Value.ToString();
                string feedListHash = feedListXml.Item(i).InnerText.ToString();

                //check feed request list for a match
                while (j < feedRequestXml.Count && feedLocated == false)
                {
                    feedRequestNode = feedRequestXml.Item(j);
                    string feedRequestName = feedRequestNode.Attributes["name"].Value.ToString();

                    //checks to see if feed names match
                    if (feedRequestName == feedListName)
                    {
                        string feedRequestHash = feedRequestXml.Item(j).InnerText.ToString();

                        //checks to see if hashCodes match
                        if (feedListHash == feedRequestHash)
                        {
                            //if name and code match, set status to ok
                            attr.Value = "ok";

                            Debug.WriteLine(feedListName + " name and hash match. Status: 'ok'");
                        }
                        else 
                        {
                            //if hashCodes don't match, set status attribute to updated
                            attr.Value = "updated";

                            Debug.WriteLine(feedListName + " name matched but hash did not. Status: 'updated'");
                        }
                        feedListNode.Attributes.Append(attr);
                        feedLocated = true;
                    }
                    else
                    {
                        //names didn't match, checking to see if we're at the end of  the request list
                        if (j + 1 == feedRequestXml.Count)
                        {
                            //file name wasn't found in the request list, set status attribute to missing
                            attr.Value = "missing";
                            feedListNode.Attributes.Append(attr);
                            feedLocated = true;
                            j = 0;

                            Debug.WriteLine("Reached the end of the file request list without a match. Status: 'missing'");
                        }
                        //file name wasn't located on this pass, move to next record
                        j++;
                    }
                }
                feedLocated = false;
            }
        }
        finally
        {
            Debug.WriteLine("Result file has been written out at " + _resultPath);
        }

        feedListXmlDoc.Save(_resultPath);
    }
于 2013-08-20T13:49:08.940 回答
0

看看不同,从我在 CodePlex 上的开源项目CodeBlocks 来看,它是为这种情况而设计的。它也可以在 Nuget 上作为“不同”使用

于 2013-08-19T17:09:00.210 回答