В настоящее время я поддерживаю веб-приложение, которое я написал около года назад для работы. По сути, это позволяет пользователям создавать собственные шаблоны отчетов 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
выдается с сообщением «Нет контента, сгенерированного в результате операции». Поэтому я не совсем уверен, что какой-либо из них работает, но я предполагаю, что они работают, поскольку для предыдущих замен не выдается никаких исключений.
Я не могу понять, что это значит, и у 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(String newNode)
...Обрезаны частные символы приложения...
В справочнике MSDN для ReplaceSelf
описаны исключения, которые он генерирует, но единственное System.InvalidOperationException
возникает исключение, когда «XpathNavigator не расположен на элементе, тексте, инструкции обработки или узле комментария». Из отладчика Visual Studio я могу подтвердить, что он расположен на элементе. Мой код согласен. XPathNavigator
, указывающие на заполнители, на самом деле являются клонами System.Xml.XPath.XPathNodeIterator.Current
(все они добавляются в список, который преобразуется в массив и повторяется на этапе замены).
Что не так (что на самом деле означает исключение) и как мне это исправить?
Добавить: класс, который на самом деле выдает исключение (System.Xml.DocumentXmlWriter
), похоже, не задокументирован в MSDN (или, по крайней мере, я не смог найти его ни с помощью поиска Google, ни с помощью поиска MSDN).
Добавить: я определил, что данные для одной замены, вызвавшей проблему, представляют собой одиночный пробел (т. е. " "
). Я не понимаю, почему это может быть проблемой для XPathNavigator
, но, видимо, это так... Кажется, пустая строка (т.е. ""
) тоже. Возможно, проблема заключается в попытке заменить элемент только пробелами. Хотя я не понимаю, почему это должно быть проблемой.