1

我目前正在维护一个大约一年前为工作编写的 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)
...截断私有应用程序符号...

MSDN 参考描述了它引发的ReplaceSelf异常,但引发的唯一System.InvalidOperationException异常是“XPathNavigator 未定位在元素、文本、处理指令或注释节点上”时。在 Visual Studio 调试器中,我可以确认它位于元素上。我的代码同意。指向占位符的XPathNavigator' 实际上是System.Xml.XPath.XPathNodeIterator.Current(所有这些都被添加到列表中,列表被转换为数组,并在替换阶段迭代)。

出了什么问题(异常实际上是什么意思),我该如何解决?

附加:实际上引发异常的类 ( System.Xml.DocumentXmlWriter) 似乎没有记录在 MSDN 上(或者至少,我无法通过 Google 搜索或 MSDN 搜索找到它)。

追加:我已经确定导致问题的一个替换的数据只是一个空格(即" ")。我不明白为什么这可能是一个问题XPathNavigator,但显然它是......似乎也是一个空字符串(即,"")。那么问题可能是试图用只有空格替换一个元素。我不明白为什么这应该是一个问题。

4

2 回答 2

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 对象。

于 2011-08-12T11:57:52.287 回答
0

这不是您的问题的答案(无论如何这已经很老了),但是对于来这里寻找原因的人来说,No content generated as the result of the operation.在叶节点上设置 InnerXml 的值时,您可能会看到使用成功SetValue

为什么它对叶节点很重要,我不能肯定地告诉你。我猜这是尝试将节点解析为简单字符串的错误。

在此 stackoverflow 问题此 InfoPathDev 问题中查看有关 Value 和 InnerXml 之间区别的更多信息(我认为这个问题更有帮助)。

因此,如果我在此节点上放置了一个 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.
于 2014-08-22T16:31:35.247 回答