System.Xml.XmlDocument, System.Xml.XPath.XPathNavigator {ReplaceSelf, OuterXml}: замена заполнителей в документе - PullRequest
1 голос
/ 05 мая 2011

В настоящее время я поддерживаю веб-приложение, которое я написал около года назад для работы.В основном это позволяет пользователям создавать собственные шаблоны отчетов XHTML.Я использую XmlDocument, XPathNavigator, et.и др.для проверки, очистки и замены заполнителей данными.

В большинстве случаев это работает нормально, но я только что понял, что на самом деле я не заменял элементы заполнителей данными, а заменялтекст заполнителя с текстом данных.

Придуманный пример:

<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 с сообщением "В результате не генерируется контентоперации ".Так что я не совсем уверен, что кто-то из них работает, но я предполагаю, что это так, потому что для предыдущих замен нет исключений.

Я не могу понять, что это значит, и у Google есть только 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)
... Пропущенные символы частного приложения ...

The Ссылка MSDN для ReplaceSelf описывает исключения, которые оно выдает, но единственное исключение System.InvalidOperationException, которое генерируется, когда «XPathNavigator не расположен на элементе, тексте, инструкции обработки или узле комментария».Из отладчика Visual Studio я могу подтвердить, что он расположен на элементе.Мой код согласен.XPathNavigator, указывающие на заполнители, на самом деле являются клонами System.Xml.XPath.XPathNodeIterator.Current (все они добавляются в список, который преобразуется в массив и повторяется во время фазы подстановки).

Чтонеправильно (что на самом деле означает исключение) и как я могу это исправить?

Append: Класс, который на самом деле выдает исключение (System.Xml.DocumentXmlWriter), похоже, незадокументировано в MSDN (или, по крайней мере, я не смог найти его ни с помощью поиска Google, ни с помощью поиска MSDN).

Приложение: Я определил, что данные для одной замены вызывают проблемуэто просто один пробел (то есть " ").Я не понимаю, почему это может быть проблемой для XPathNavigator, но, видимо, это так ... Кажется, пустая строка (то есть "") тоже.Возможно, проблема заключается в попытке заменить элемент только пробелами.Я не понимаю, почему это должно быть проблемой.

Ответы [ 2 ]

1 голос
/ 12 августа 2011

Я также получаю то же сообщение об ошибке:

Нет содержимого, сгенерированного в результате операции

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 без записи какого-либо узла.

0 голосов
/ 22 августа 2014

Это не ответ на ваш вопрос (который в любом случае довольно старый), но для людей, которые пришли сюда и ищут причину No content generated as the result of the operation., которая возникает при установке значения InnerXml на листовом узле, вы можете увидетьуспех, используя вместо этого SetValue.

Почему это важно для конечного узла, я не могу сказать вам точно.Я предполагаю, что это ошибка при попытке разобрать узлы в простой строке.

См. Дополнительную информацию о разнице между Value и InnerXml в этом вопросе stackoverflow или в этом InfoPathDevвопрос (на мой взгляд, этот вопрос более полезен).

Итак, если у меня есть 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.
...