<xsl:copy-of select="//concat(text()[1], ' ')"/>
Эта инструкция фактически не копирует полный текст из документа XML!
Вот пример:
<a>
<b>X1<c>Y</c>X2</b>
</a>
Когда вышеуказанный документ XML, обрабатывается с помощью следующего преобразования (который включает в себя только инструкции XSLT из предоставленного кода):
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:copy-of select="//concat(text()[1], ' ')"/>
</xsl:template>
</xsl:stylesheet>
результатом является :
X1 Y
Как мы видим, строка "X2
" не Прес nt на выходе.
Другая проблема заключается в том, что невозможно определить, какие именно пространства были добавлены как разделители между любыми двумя текстовыми узлами.
Другими словами, полученный результат не является точно конкатенацией текстовых узлов XML-документов.
В случае, если вы не связаны с последней проблемой, один правильный XPath 2.0 выражения, которая соединяет все текстовые узлы в документе, используя пространство, как разделитель:
//string-join(text(), ' ')
С этой коррекцией, ваш код при условии, становится:
<xsl:variable name="text-accumulated">
<xsl:for-each select="collection($collection-string)">
<xsl:copy-of select="//string-join(text(), ' ')"/>
</xsl:for-each>
</xsl:variable>
ли value-of
лучший вариант, чем copy-of
?
Неправильно сравнивать, какая из этих двух инструкций XSLT «лучше», потому что они служат для разных целей.
<xsl:value-of>
производит единый текстовый узел которого строковое значение есть конкатенация строковых значений выбранных элементов (возможно, разделенных сепаратором-строки, если указан атрибут separator
.
С другой стороны ,
<xsl:copy-of>
производит копию последовательности узлов и/или атомарных значений, с каждым новым узлом, содержащего копию всех детей, атрибуты и (по умолчанию) пространства имен исходного узла, рекурсивно.
Очевидно, что две инструкции не взаимозаменяемы, и каждый из них может быть использован для решения другой проблемы.
Это работает для меня. Но я всегда осторожен с использованием //
можно использовать шаблоны вместо абсолютных выражений. В вашем случае что-то вроде этого:
<xsl:variable name="text-accumulated">
<xsl:apply-templates select="collection($collection-string)" mode="mergeText"/>
</xsl:variable>
<xsl:template match="text()" mode="mergeText">
<xsl:value-of select="concat(., ' ')"/>
</xsl:template>
Does ' 'не хватает ? Что касается глубоких копий, вы хотите вообще создать какие-либо узлы? Похоже, вы просто хотите получить строковое значение. –
Мартин, это не приносит желаемого результата, но я буду работать над ним - это, безусловно, более сжатый код. Хороший намек на копию: это может привести к ошибочному узлу(), значение-нет. – Paulb
Ваш 'select =" // concat (text() [1], '') "' на 'xsl: copy-of' в любом случае вычисляет строки, и этот способ скорее будет работать как' xsl: sequence'. Это может помочь, если вы разместите три или четыре фрагмента примеров документов, в которых вы хотите объединить текст или строковое значение, плюс желаемый результат, тогда нам легче сказать, чего вы хотите достичь, и предложить альтернативы. '// concat (text() [1], '')' выглядит необычно для меня, что я не уверен, что вы хотите вычислить с ним, не видя некоторых образцов. –