我是 XML 和 C# 新手,因此在实现以下内容时遇到了一些困难。希望有人能指出我正确的方向。因此,我正在使用 OpenXML 2.5 在 C# 中进行开发,并且在创建字体后尝试检查该字体是否已存在于字体集合中。如果它已经存在,那么我想返回字体的索引。
我一直致力于编写一种有效的方法来比较这些 Font 对象,并且我相信比较它们各自的 XML 代码是正确的方法。我相信这些 Font 对象是 XML 代码的包装器。所以我认为我应该能够比较两个 XML 元素并确定字体是否已经存在。
这有什么意义吗?这是一个例子,因为我担心我的解释过于复杂。
1. 基本上,我想知道是否是这样:
<x:font>
<x:b />
<x:sz val="18" />
<x:color theme="3" />
<x:name val="Cambria" />
<x:family val="2" />
<x:scheme val="major" />
</x:font>
2. 已经存在于此处:
<x:fonts count="18" x14ac:knownFonts="1" xmlns:x14ac="http://schemas.microsoft.com/office/spreadsheetml/2009/9/ac" xmlns:x="http://schemas.openxmlformats.org/spreadsheetml/2006/main">
<x:font>
<x:sz val="11" />
<x:color theme="1" />
<x:name val="Calibri" />
<x:family val="2" />
<x:scheme val="minor" />
</x:font>
<x:font>
<x:sz val="11" />
<x:color theme="1" />
<x:name val="Calibri" />
<x:family val="2" />
<x:scheme val="minor" />
</x:font>
<x:font>
<x:b />
<x:sz val="18" />
<x:color theme="3" />
<x:name val="Cambria" />
<x:family val="2" />
<x:scheme val="major" />
</x:font>
<x:font>
<x:b />
<x:sz val="15" />
<x:color theme="3" />
<x:name val="Calibri" />
<x:family val="2" />
<x:scheme val="minor" />
</x:font>
</x:fonts>
3. 该方法返回 Font 的索引。所以在这个例子中我的函数将返回
2
。
如有任何帮助,我们将不胜感激!
谢谢, 贾斯汀
查看用于查询 XMLDocuments 的 XPath,然后您可以通过 XPath 查询在 XMLDocument 上使用 FindNode()。
但是,它不会返回索引号。除非另有指示,否则 XML 节点不会排序,因此说“这是第三个”的想法不会完成,因为下次您查看时它可能是第五个! (可能不是,但是类似的行为符合 XML 规范)。不过,您可以做的是获取实际的节点 (),从中您可以获取包含它的父节点 ()。
感谢您的帮助,但实际上从 sdk 中找到了一种更简单的方法。结果发现每个 OpenXml 对象都有一个名为
OuterXml
的方法。
根据微软定义:
OuterXml: Gets the markup that represents the current element and all of its child elements.
比
InnerXml: Gets or sets the markup that represents only the child elements of the current element.
好多了
所以我可以简单地做:
private Stylesheet _stylesheet = _workbookPart.WorkbookStylesPart.Stylesheet;
public int GetFontIndex(Font font)
{
int index = 0;
foreach (var existingFont in _stylesheet.Descendants<Font>())
{
if (font.OuterXml.Equals(existingFont.OuterXml)) return index;
index++;
}
return -1;
}
在 OpenXML v3 中引入了一种更有效的方法:OpenXmlElementComparers
它会让您能够
OpenXmlElementComparers.Default.Equals(a,b)
。
还可以通过使用 OpenXmlElementEqualityOptions 创建来更精细地控制如何定义相等性
OuterXml 属性曾经是解决此问题的最简单方法。然而,由于如此处所述的大量分配,性能并不是很好。