【问题标题】:System.Xml.XmlDocument, System.Xml.XPath.XPathNavigator{ReplaceSelf,OuterXml}: Replacing Placeholders In DocumentSystem.Xml.XmlDocument、System.Xml.XPath.XPathNavigator{ReplaceSelf,OuterXml}:替换文档中的占位符
【发布时间】:2011-05-04 20:47:00
【问题描述】:

我目前正在维护一个大约一年前为工作而编写的 Web 应用程序。基本上,它允许用户创建自定义 XHTML 报告模板。我使用XmlDocumentXPathNavigator 等。人。用数据验证、清理和替换占位符。

它在大多数情况下都可以正常工作,但我刚刚意识到我实际上并没有用数据替换占位符元素,而是用数据文本替换占位符的文本。

人为的例子:

<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)
...截取私有应用程序符号...

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

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

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

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

【问题讨论】:

    标签: .net xmldocument xpathnavigator outerxml


    【解决方案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 对象。

    【讨论】:

      【解决方案2】:

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

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

      查看更多关于 Value 和 InnerXml in this stackoverflow questionin 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.
      

      【讨论】:

        猜你喜欢
        • 2010-09-15
        • 1970-01-01
        • 2013-04-08
        • 2013-12-20
        • 1970-01-01
        • 1970-01-01
        • 2010-09-29
        • 1970-01-01
        相关资源
        最近更新 更多