我目前正在维护一个大约一年前我写的工作的Web应用程序。基本上它允许用户创建自定义XHTML报告模板。我使用XmlDocument
,XPathNavigator
等。人。用数据验证,消毒和替换占位符。
它在大多数情况下工作正常,但我刚刚意识到我实际上并没有用数据替换占位符元素,而是用数据文本替换占位符的文本。
受挫的例子:
<span class="my-placeholder">{CompanyName}</span>
会变成......
<span class="my-placeholder">Castopulence</span>
过去这不是一个真正的问题,因为模板只进行了一次处理;当用户选择针对一组选定数据运行它时。但是,现在,我们为他们提供了预览结果输出并在打印前进行修改的选项。结果是它被替换引擎多次处理:首先生成原始输出,然后再次“修改”输出“打印”。替换引擎找到一个实际上是数据的占位符,无法找到要替换的相应数据元素,并且该进程因异常而失败。
原始代码使用XPathNavigator.InnerXml
属性将占位符元素的内容从“{CompanyName}”更改为“Castopulence”(例如):
placeholder.InnerXml = this.Server.HtmlEncode(value);
因此,如果我想直接替换此占位符元素,我会改为使用XPathNavigator.OuterXml
:
placeholder.OuterXml = this.Server.HtmlEncode(value);
这似乎在大多数情况下都有效,或者至少我认为它确实有效,但看似随机的替换总是会导致System.InvalidOperationException
抛出一条消息,“没有因操作而生成的内容“。所以我不确定它们中的任何一个是否正常工作,但我认为它们是因为以前的替换都没有例外。
我无法弄清楚这意味着什么,谷歌只有4个结果用于异常消息的确切短语,每个都使用我不会说的语言。谷歌翻译他们没有发现任何相关内容。
实验上我尝试了XPathNavigator.ReplaceSelf
,它似乎完成了同样的事情,但遗憾的是同一个内部调用抛出了同样的异常。
两种情况下的堆栈跟踪:
在System.Xml.DocumentXmlWriter.Close(WriteState currentState)
在System.Xml.XmlWellFormedWriter.Close()
在System.Xml.XPath.XPathNavigator.ReplaceSelf(XmlReader newNode)
在System.Xml.XPath.XPathNavigator.ReplaceSelf(String newNode)
...剪切私有应用程序符号......
ReplaceSelf
System.InvalidOperationException
描述了它抛出的异常,但抛出的唯一XPathNavigator
异常是“当XPathNavigator没有定位在元素,文本,处理指令上时,或评论节点。“从Visual Studio调试器,我可以确认它位于元素上。我的代码同意了。指向占位符的System.Xml.XPath.XPathNodeIterator.Current
实际上是System.Xml.DocumentXmlWriter
的克隆(所有这些都被添加到列表中,转换为数组,并在替换阶段迭代)。
有什么问题(异常实际意味着什么)以及如何解决?
附加:实际上抛出异常(" "
)的类似乎没有在MSDN上记录(或者至少,我在Google搜索中找不到它也不是MSDN搜索)。
附加:我已经确定导致问题的一个替换的数据只是一个单一空格(即XPathNavigator
)。我不明白为什么这可能是""
的问题,但显然它是......似乎是一个空字符串(即{{1}})也是如此。也许问题是尝试用空格替换元素。我不明白为什么这应该是一个问题。
答案 0 :(得分:1)
我也收到了同样的错误消息:
操作无法生成任何内容
XmlWriter writer = replaceTextIterator.Current.ReplaceRange(replaceTextIterator.Current);
XPathNodeIterator iterator5 = replaceTextIterator.Current.SelectChildren(XPathNodeType.All);
while (iterator5.MoveNext())
{
writer.WriteNode(iterator5.Current, true);
}
writer.Close();
如果iterator.count = 0,我收到该错误消息,因此不要在不写任何节点的情况下关闭xmlwriter对象。
答案 1 :(得分:0)
这不是你的问题的答案(无论如何都是这个问题),但对于那些来到这里寻找在叶子节点上设置InnerXml值时发生No content generated as the result of the operation.
的原因的人来说,你可能会使用SetValue
代替成功。
为什么它对叶节点很重要,我无法肯定地告诉你。我猜想尝试将节点解析成一个简单的字符串是错误的。
查看有关Value和InnerXml in this stackoverflow question之间差异的更多信息,或in this InfoPathDev question(在我看来,这个更有帮助)。
所以如果我在这个节点上放置了一个XPathNavigator:
<my:group2 my:field4="Hi"> <my:field1>Hello</my:field1> <my:field2 my:field5="yay">Goodbye</my:field2> <my:field3></my:field3> </my:group2> InnerXml would be: <my:field1>Hello</my:field1> <my:field2 my:field5="yay">Goodbye</my:field2> <my:field3></my:field3> And Value would be: Hello Goodbye For leaf nodes, InnerXml and Value should typically be the same, but I'd suggest using Value for getting a node's value as that's what it's intended for.