当前位置: 首页 > 面试题库 >

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

杨和蔼
2023-03-14
问题内容

我正在尝试编写一种简单的算法来读取两个XML文件,它们的节点和结构完全相同,但子节点内部的数据不一定相同,顺序也不相同。我该如何使用Microsoft的XML Diff .DLL创建一个简单的实现来创建第三个临时XML(即两个第一个XML之间的差异)?

MSDN上的XML Diff:

XML差异和补丁工具

XML Diff和Patch GUI工具

要比较的两个不同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文件,但是我还没有。我要做的就是从“ GP”子节点开始,在第三个XML文件中显示每个节点的每个数值的差。

到目前为止,我有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”节点,前三个子对象不必进行比较…我该如何实现呢?


问题答案:

有两种直接的解决方案:

解决方法1。

您可以首先对两个文档应用简单的转换,这将删除不应比较的元素。然后,将两个文档的结果与您当前的html" target="_blank">代码完全比较。这是转换:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="Name|Team|Pos"/>
</xsl:stylesheet>

当此转换应用于提供的XML文档时:

<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>
        <PP>10</PP>
        <SH>1</SH>
        <GW>3</GW>
        <Shots>0</Shots>
        <ShotPctg>154</ShotPctg>
        <TOIPerGame>20.8</TOIPerGame>
        <ShiftsPerGame>21:54</ShiftsPerGame>
        <FOWinPctg>22.6</FOWinPctg>
    </Player>
</Stats>

生成所需的结果文件:

<Stats Date="2011-01-01">
   <Player Rank="1">
      <GP>39</GP>
      <G>32</G>
      <A>33</A>
      <PlusMinus>20</PlusMinus>
      <PIM>29</PIM>
      <PP>10</PP>
      <SH>1</SH>
      <GW>3</GW>
      <Shots>0</Shots>
      <ShotPctg>154</ShotPctg>
      <TOIPerGame>20.8</TOIPerGame>
      <ShiftsPerGame>21:54</ShiftsPerGame>
      <FOWinPctg>22.6</FOWinPctg>
   </Player>
</Stats>

解决方案2。

这是一个完整的XSLT 1.0解决方案(仅出于方便起见,第二个XML文档已嵌入转换代码中):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vrtfDoc2">
  <Stats Date="2011-01-01">
    <Player Rank="2">
        <Name>John Smith</Name>
        <Team>NY</Team>
        <Pos>D</Pos>
        <GP>38</GP>
        <G>32</G>
        <A>33</A>
        <PlusMinus>15</PlusMinus>
        <PIM>29</PIM>
        <PP>10</PP>
        <SH>1</SH>
        <GW>4</GW>
        <Shots>0</Shots>
        <ShotPctg>158</ShotPctg>
        <TOIPerGame>20.8</TOIPerGame>
        <ShiftsPerGame>21:54</ShiftsPerGame>
        <FOWinPctg>22.6</FOWinPctg>
    </Player>
  </Stats>
 </xsl:variable>

 <xsl:variable name="vDoc2" select=
  "document('')/*/xsl:variable[@name='vrtfDoc2']/*"/>

 <xsl:template match="node()|@*" name="identity">
  <xsl:param name="pDoc2"/>
  <xsl:copy>
   <xsl:apply-templates select="node()|@*">
    <xsl:with-param name="pDoc2" select="$pDoc2"/>
   </xsl:apply-templates>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
  <xsl:apply-templates select="*">
   <xsl:with-param name="pDoc2" select="$vDoc2"/>
  </xsl:apply-templates>

  -----------------------

  <xsl:apply-templates select="$vDoc2">
   <xsl:with-param name="pDoc2" select="/*"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="Player/*">
  <xsl:param name="pDoc2"/>
  <xsl:if test=
   "not(. = $pDoc2/*/*[name()=name(current())])">
   <xsl:call-template name="identity"/>
  </xsl:if>
 </xsl:template>

 <xsl:template match="Name|Team|Pos" priority="20"/>
</xsl:stylesheet>

当将此变换应用于与上述相同的第一个文档时,将生成正确的衍射图:

<Stats Date="2011-01-01">
   <Player Rank="1">
      <GP>39</GP>
      <PlusMinus>20</PlusMinus>
      <GW>3</GW>
      <ShotPctg>154</ShotPctg>
   </Player>
</Stats>

  -----------------------

  <Stats xmlns:xsl="http://www.w3.org/1999/XSL/Transform" Date="2011-01-01">
   <Player Rank="2">
      <GP>38</GP>
      <PlusMinus>15</PlusMinus>
      <GW>4</GW>
      <ShotPctg>158</ShotPctg>
   </Player>
</Stats>

运作方式:

  1. 将该转换应用于第一个文档,并将第二个文档作为参数传递。

  2. 这将生成一个XML文档,其唯一的叶子元素节点的值与第二个文档中相应的叶子元素节点的值不同。

  3. 执行与上面1.中相同的处理,但是这次在第二个文档上,将第一个文档作为参数传递。

  4. 这将产生第二个差异图:一个XML文档,其唯一的叶子元素节点的值**与第一个文档中相应的叶子元素节点的值不同



 类似资料:
  • 我有两个文件-file1.txt和file2.txt。我想用powershell比较这两个文件,并生成第三个文件(file3.txt),它包含从file1.txt开始的所有行减去file2.txt中的行 你能想出什么办法来做这件事吗?

  • 我有两个XML文件,需要仅使用XSLT 1.0将其合并为第三个XML文件 文件一: 文件二: 最终结果应该输出到第三个名为output的文件中。xml,应该如下所示 我正在使用记事本将XSLT应用于第二个文件,我尝试使用 添加了编辑XSLT

  • 我试图比较两个xml文件并显示差异,如果找到的话。 目前,我正在使用XML Diff来查找差异。 也查看了xnode.deepeQuals,但它也返回是否有任何区别。但不是什么区别。 任何帮助都很感激

  • 我试图比较两个XML文件。我的要求是比较新旧xml文件,如果有任何差异,将其合并到新的xml文件中。 但我也想要差异。请告诉我怎样才能得到不同之处。 我已经尝试过XMLUnit,但我不想使用它。

  • 问题内容: 我想比较两个每个都有三列的文本文件。一个文件有999行,另一个文件有757行。我希望将不同的242行存储在不同的文件中。我使用随机网络生成器创建了第一个文件(999行)(999行是边,第三列是第一,第二列之间的权重- 源节点和目标节点)。 文件格式-文件1、2 我试过了 逐行比较两个文件,并在另一个文件中产生差异,并 找到两个文本文件之间的差异,每行一个,并且http://www.da