Я ищу элегантное решение XSLT 1.0 или 2.0 для следующей задачи преобразования. Я упростил разметку ниже, так что «a» - это начальный элемент вехи, а «b» - это конечный элемент вехи. Все между «a» и «b» должно быть обернуто элементом «c».XSLT-преобразование элементов одноэлементности/вехи
Входной сигнал:
<doc>
<line>Text text <a/>text<b/></line>
<line>Text <a/>text text</line>
<line>Text<b/> text <a/>text</line>
<line>Text text text</line>
<line>Text text<b/> text</line>
</doc>
Выход:
<doc>
<line>Text text <c>text</c></line>
<line>Text <c>text text</c></line>
<line><c>Text</c> text <c>text</c></line>
<line><c>Text text text</c></line>
<line><c>Text text</c> text</line>
</doc>
В реальной случае, есть по крайней мере 5 вариаций каждого из а/б/с элементами для удовлетворения. Существуют также десятки тысяч строк, многие из которых не содержат a/b или их вариаций. В реальном случае также есть группа секций, разделяющих «сек», где поведение a/b по-прежнему должно работать.
Наше первоначальное решение подразумевало использование предшествующих :: *, но это, очевидно, приносит значительные проблемы с производительностью для больших XML-документов, поэтому это не приемлемое решение.
Возможно, вы сможете решить проблему с производительностью, просто используя предыдущий, а не предыдущий. Если строки содержат гораздо большее количество узлов, чем показанные, предыдущие братья и последующие братья не должны быть чрезмерно дорогими. –
Спасибо @MichaelKay. В настоящее время мы используем предыдущий брат, но он по-прежнему не масштабируется, потому что нам нужно оглянуться назад по всему документу, чтобы правильно определить текущее состояние строки. Я предполагаю, что нам придется переключиться на подход обработки SAX, чтобы решить эту проблему, используя простой набор флагов состояния. –
ОК, я думаю, я не оценил семантику ваших веха. Это предполагает, что вам нужно двигаться вперед по линиям, поддерживая состояние либо с помощью рекурсии, либо в XSLT 3.0 с помощью xsl: iterate. –