1

私は現在、約 1 年ほど前に仕事のために書いた Web アプリケーションを保守しています。基本的に、ユーザーはカスタム XHTML レポート テンプレートを作成できます。XmlDocument、、などを使用しますXPathNavigator。アル。プレースホルダーをデータで検証、サニタイズ、および置換します。

ほとんどの場合は問題なく動作しますが、プレースホルダー要素を実際にデータに置き換えているのではなく、プレースホルダーのテキストをデータ テキストに置き換えていることに気付きました。

考案された例:

<span class="my-placeholder">{CompanyName}</span>

なるだろう...

<span class="my-placeholder">Castopulence</span>

テンプレートは 1 回しか処理されなかったため、これは以前は実際には問題ではありませんでした。ユーザーが選択したデータのセットに対して実行することを選択したとき。ただし、現在は、結果の出力をプレビューして、印刷する前に変更するオプションを提供しています。この結果、置換エンジンによって複数回処理されます。最初に元の出力を生成し、変更された出力が「印刷」されるときに再度処理されます。置換エンジンは、実際にはデータであるプレースホルダーを見つけ、置換する対応するデータ要素を見つけることができず、プロセスは例外で失敗します。

元のコードでは、XPathNavigator.InnerXmlプロパティを使用して、プレースホルダー要素の内容を "{CompanyName}" から "Castopulence" に変更しました (例):

placeholder.InnerXml = this.Server.HtmlEncode(value);

したがって、このプレースホルダー要素を完全に置き換えたい場合は、代わりに次を使用するのが合理的ですXPathNavigator.OuterXml

placeholder.OuterXml = this.Server.HtmlEncode(value);

これはほとんどの場合に機能するように見えますが、少なくとも私は機能すると思いますが、一見ランダムな置換により、常にSystem.InvalidOperationException「操作の結果としてコンテンツが生成されません」というメッセージがスローされます。そのため、それらのいずれかが機能しているとは確信していませんが、以前の置換に対して例外がスローされていないため、機能していると思います。

これが何を意味するのかよくわかりません。Google には、例外メッセージの正確なフレーズの結果が 4 つしかありません。それぞれ、私が話せない言語で書かれています。それらをGoogleで翻訳すると、関連するものは何も明らかになりませんでした。

実験的に試してみXPathNavigator.ReplaceSelfましたが、同じことを達成しているようですが、残念ながら同じ内部呼び出しから同じ例外がスローされます。

どちらの場合もスタック トレース:

System.Xml.DocumentXmlWriter.Close (WriteState currentState)
で System.Xml.XmlWellFormedWriter.Close()
で System.Xml.XPath.XPathNavigator.ReplaceSelf (XmlReader newNode)
で System.Xml.XPath.XPathNavigator.ReplaceSelf (文字列 newNode) で
...プライベート アプリケーションのシンボルを切り取った...

スローされる例外については、MSDN リファレンスReplaceSelf説明されていますが、スローされる唯一のSystem.InvalidOperationException例外は、「XPathNavigator が要素、テキスト、処理命令、またはコメント ノードに配置されていない」場合です。Visual Studio デバッガーから、要素に配置されていることを確認できます。私のコードは同意します。XPathNavigatorプレースホルダーを指している は、実際には のクローンです(System.Xml.XPath.XPathNodeIterator.Currentこれらはすべてリストに追加され、配列に変換され、置換フェーズで反復処理されます)。

何が問題なのか (例外は実際には何を意味するのか)、どうすれば修正できますか?

追加:実際に例外をスローしているクラス ( System.Xml.DocumentXmlWriter) は、MSDN で文書化されていないようです (少なくとも、Google 検索でも MSDN 検索でも見つかりませんでした)。

追加:問題を引き起こしている 1 つの置換のデータは、単一のスペース (つまり、" ") であると判断しました。なぜこれが の問題になるのかはわかりませんが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代わりに使用して成功する可能性があります。

なぜ葉ノードにとって重要なのか、はっきりとは言えません。ノードを単純な文字列から解析しようとしたことによるエラーだと思います。

Value と InnerXml の違いの詳細については、この stackoverflow question、またはこの 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.
于 2014-08-22T16:31:35.247 に答える