我有一个类似于
的XDocument<root>
<a>
<b foo="1" bar="2" />
<b foo="3" bar="4" />
<b foo="5" bar="6" />
<b foo="7" bar="8" />
<b foo="9" bar="10" />
</a>
</root>
我希望将属性foo更改为其他内容,将属性栏更改为其他内容。我怎么能轻松做到这一点?我当前的版本(下面)堆栈溢出大文档,并有一个可怕的气味。
string dd=LoadedXDocument.ToString();
foreach (var s in AttributeReplacements)
dd = dd.Replace(s.Old+"=", s.New+"=");
答案 0 :(得分:3)
使用StringBuilder
进行文本搜索和替换时应该这样做,以避免在循环中创建字符串的常见问题(大量垃圾)。也很难防止误报(如果文本节点中的文本与文本节点匹配会怎样?)
更好的选择,有不同的权衡,包括:
这些#3避免了将整个文档加载到内存中。 #2需要XSLT技能,但很容易允许任意数量的替换(XSLT的核心可以是模板,在运行时注入新的旧属性对)。 #1可能是最简单的,但整个文档在内存中,以及处理多个替换的开销。
我可能会将XSL读取器/写入器方法作为备份来看待XSLT。
然而#1应该是最简单的实现,例如(在其他细节中忽略XML命名空间):
using System.Xml.Linq;
using System.Xml.XPath;
var xdoc = XDocument.Load(....);
var nav = xdoc.CreateNavigator();
foreach (repl in replacements) {
var found = (XPathNodeIterator) nav.Evaluate("//@" + repl.OldName);
while (found.MoveNext()) {
var node = found.Current;
var val = node.Value;
node.DeleteSelf(); // Moves ref to parent.
node.CreateAttribute("", repl.NewName, "", val);
}
}
最终的选择将取决于平衡性能(尤其是处理大型文档时的内存)和复杂性。但只有你(和你的团队)可以打电话。
答案 1 :(得分:2)
这是一个完整的XSLT解决方案:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:reps"
exclude-result-prefixes="my"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<my:replacements>
<foo1 old="foo"/>
<bar1 old="bar"/>
</my:replacements>
<xsl:variable name="vReps" select=
"document('')/*/my:replacements/*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:variable name="vRepNode" select=
"$vReps[@old = name(current())]"/>
<xsl:variable name="vName" select=
"name(current()[not($vRepNode)] | $vRepNode)"/>
<xsl:attribute name="{$vName}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时,会生成所需的结果:
<root>
<a>
<b foo1="1" bar1="2"/>
<b foo1="3" bar1="4"/>
<b foo1="5" bar1="6"/>
<b foo1="7" bar1="8"/>
<b foo1="9" bar1="10"/>
</a>
</root>
请注意这是一个通用的解决方案,允许在不修改代码的情况下指定和修改任何替换列表。替换可以在单独的XML文件中,以便于维护。