如何在 C# 中比较 XmlDocument 的两个 XmlNode?
How to compare two XmlNodes of XmlDocument in C#?
这是一个示例 xml。如果要在某种意义上添加新字体,则在添加到首选项之前,所有现有字体都要与新字体进行比较。
在 XmlDocument 的情况下如何检查节点(字体)是否已经存在?
<preferences>
<font role="console">
<size>9</size>
<fname>Courier</fname>
</font>
<font role="default">
<fname>Times New Roman</fname>
<size>14</size>
</font>
<font role="titles">
<size>10</size>
<fname>Helvetica</fname>
</font>
</preferences>
Xnode 有一个称为 DeepEqual 的功能来比较节点。 XmlNode可以通过简单的解析转换成Xnode。
XElement XmlElementToXElement(XmlNode e)
{
return XElement.Parse(e.OuterXml);
}
所以,从这里开始会更容易。如果两个节点相等,下面的方法将 return 为真。
bool XmlNode_DeepEquals(XmlNode node1, XmlNode node2)
{
XElement tempX = XmlElementToXElement(node2);
XElement searchX = XmlElementToXElement(node1);
return XNode.DeepEquals(tempX, searchX))
}
此方法用于比较节点列表。
bool isNodeAlreadyExists(XmlNode searchNode, XmlNodeList list)
{
bool exists = false;
foreach (XmlNode node in list)
{
if (XmlNode_DeepEquals(searchNode, node))
{
exists = true;
}
}
return exists;
}
一种方法是创建几个 classes 来表示 XML 文档并实现 IEquatable<T> Interface
.
https://dotnetfiddle.net/QZFwDy
类 对于 XML
[XmlRoot(ElementName = "font")]
public class Font : IEquatable<Font>
{
[XmlElement(ElementName = "size")]
public string Size { get; set; }
[XmlElement(ElementName = "fname")]
public string Fname { get; set; }
[XmlAttribute(AttributeName = "role")]
public string Role { get; set; }
public bool Equals(Font font)
{
if (font == null) return false;
return (Size == font.Size) && (Fname == font.Fname) && (Role == font.Role);
}
}
[XmlRoot(ElementName = "preferences")]
public class Preferences
{
[XmlElement(ElementName = "font")]
public List<Font> Font { get; set; }
}
然后使用Preferences
class反序列化XML。反序列化文档后,利用 List<T>.Contains(T item)
方法查看字体节点是否存在。 .Contains
方法将调用 Font
class 中 Equals
的实现。
演示代码
static void Main(string[] args)
{
Preferences preferences = null;
var xmlString = Data.XML;
using (var stream = new StringReader(xmlString))
{
var serializer = new XmlSerializer(typeof(Preferences));
preferences = (Preferences)serializer.Deserialize(stream);
}
var node0 = new Font()
{
Fname = "New One",
Role = "console",
Size = "12"
};
var node1 = new Font()
{
Fname = "Helvetica",
Role = "titles",
Size = "10"
};
if (preferences.Font.Contains(node0))
{
// Not expecting to enter here
Console.WriteLine($"'{nameof(node0)}' is already present");
}
if (preferences.Font.Contains(node1))
{
Console.WriteLine($"'{nameof(node1)}' is already present");
}
}
这是一个示例 xml。如果要在某种意义上添加新字体,则在添加到首选项之前,所有现有字体都要与新字体进行比较。 在 XmlDocument 的情况下如何检查节点(字体)是否已经存在?
<preferences>
<font role="console">
<size>9</size>
<fname>Courier</fname>
</font>
<font role="default">
<fname>Times New Roman</fname>
<size>14</size>
</font>
<font role="titles">
<size>10</size>
<fname>Helvetica</fname>
</font>
</preferences>
Xnode 有一个称为 DeepEqual 的功能来比较节点。 XmlNode可以通过简单的解析转换成Xnode。
XElement XmlElementToXElement(XmlNode e)
{
return XElement.Parse(e.OuterXml);
}
所以,从这里开始会更容易。如果两个节点相等,下面的方法将 return 为真。
bool XmlNode_DeepEquals(XmlNode node1, XmlNode node2)
{
XElement tempX = XmlElementToXElement(node2);
XElement searchX = XmlElementToXElement(node1);
return XNode.DeepEquals(tempX, searchX))
}
此方法用于比较节点列表。
bool isNodeAlreadyExists(XmlNode searchNode, XmlNodeList list)
{
bool exists = false;
foreach (XmlNode node in list)
{
if (XmlNode_DeepEquals(searchNode, node))
{
exists = true;
}
}
return exists;
}
一种方法是创建几个 classes 来表示 XML 文档并实现 IEquatable<T> Interface
.
https://dotnetfiddle.net/QZFwDy
类 对于 XML
[XmlRoot(ElementName = "font")]
public class Font : IEquatable<Font>
{
[XmlElement(ElementName = "size")]
public string Size { get; set; }
[XmlElement(ElementName = "fname")]
public string Fname { get; set; }
[XmlAttribute(AttributeName = "role")]
public string Role { get; set; }
public bool Equals(Font font)
{
if (font == null) return false;
return (Size == font.Size) && (Fname == font.Fname) && (Role == font.Role);
}
}
[XmlRoot(ElementName = "preferences")]
public class Preferences
{
[XmlElement(ElementName = "font")]
public List<Font> Font { get; set; }
}
然后使用Preferences
class反序列化XML。反序列化文档后,利用 List<T>.Contains(T item)
方法查看字体节点是否存在。 .Contains
方法将调用 Font
class 中 Equals
的实现。
演示代码
static void Main(string[] args)
{
Preferences preferences = null;
var xmlString = Data.XML;
using (var stream = new StringReader(xmlString))
{
var serializer = new XmlSerializer(typeof(Preferences));
preferences = (Preferences)serializer.Deserialize(stream);
}
var node0 = new Font()
{
Fname = "New One",
Role = "console",
Size = "12"
};
var node1 = new Font()
{
Fname = "Helvetica",
Role = "titles",
Size = "10"
};
if (preferences.Font.Contains(node0))
{
// Not expecting to enter here
Console.WriteLine($"'{nameof(node0)}' is already present");
}
if (preferences.Font.Contains(node1))
{
Console.WriteLine($"'{nameof(node1)}' is already present");
}
}