Как я могу отсоединить смешанный контент XML с помощью инструментов C# XML, а не регулярное выражение?
Я использую "приложение 1" для создания и редактирования файлов xhtml. Он имеет возможность вводить аннотации в содержимое непустых элементов, таких как p, h1, h2, td и т. Д., Что приводит к смешанным разделам XML-кода, например:
<p>Hello <NS1:annotation [...SomeAttributes...]>everybody</NS1:annotation> out there!</p>
Для целей перевода я должен экспортировать эти файлы xhtml в "приложение 2", которое не может работать с этими внутренними элементами. Поскольку аннотации не являются частью желаемого содержимого в переводах, удаление их перед экспортом в приложение 2 было бы идеальным обходным путем:
<p>Hello everybody out there!</p>
Удаление узлов из XmlDocument надежно находит и удаляет внутренние элементы xml, но также удаляет содержимое элемента аннотации - теряя слово "все" в примере выше:
<p>Hello out there!</p>
То, что мне нужно, это скорее "открепление" содержимого этих внутренних элементов от содержимого родительского элемента. Но до сих пор я не нашел метод, использующий инструменты C# xml, выполняющие эту работу.
Пока что я сначала сохраняю файл xhtml, заново открываю его как текстовый файл и использую regedits для удаления аннотации. Я даже могу использовать методы C# для этого:
TextFile txt = new TextFile();
string s = txt.ReadFile(filename);
string pattern = @"<NS1:annotation.+>(.+)</NS1:annotation>";
string input = s;
string replacement = "$1";
Regex rgx = new Regex(pattern);
string result = rgx.Replace(input, replacement);
TextFile.Write((filename,result););
Это, несомненно, лучшее решение, поскольку оно не теряет содержание аннотации, но мне интересно, действительно ли не существует решения, основанного на C# Xml-tools, которое выполняет эту работу.
Кто-нибудь знает это?
1 ответ
Я думаю, что нашел ответ, используя XmlDocument. Ключевым моментом является то, что в смешанных узлах xml текст, окружающий узел, также может быть представлен как узлы xml. Я не знал об этом...
Следующая функция отменяет привязку содержимого смешанного узла и высвобождает его в содержимое родительского узла. Я не проверял его для узлов, содержащих несколько аннотаций, но на данный момент мне этого достаточно...
private void removeAnnotations(XmlDocument doc)
{
XmlNamespaceManager manager = new XmlNamespaceManager(new NameTable());
manager.AddNamespace("NS1","http://www.someurl.net");
XmlNodeList annotations = doc.SelectNodes("//NS1:annotation", manager);
int i = 0;
while (i < annotations.Count)
{
//in mixed xml the Siblings are xml text nodes. Therefore we write them into buffers:
string s0 = "";
if(annotations[i].PreviousSibling != null) s0 = annotations[i].PreviousSibling.InnerText;
string s2 = "";
if(annotations[i].NextSibling != null) s2 = annotations[i].NextSibling.InnerText;
//buffer the content of the annotation itself
string s1 = annotations[i].InnerText;
//buffer the link to the parent node before we remove the annotation,
XmlNode parent = annotations[i].ParentNode;
//now remove the annotation
parent.RemoveChild(annotations[i]);
//and apply the new Text to the parent element
parent.InnerText = s0 + s1 + s2;
i++;
}
}