#xml #xslt
#xml #xslt
Вопрос:
Я пытаюсь создать html-вывод в соответствии с полями в xml-файле с помощью xslt. И я называю их в соответствии с отношением grandparent-parent-child-grandchild в xml
Например:
<root>
<node1>
<node2>
<node3>Data</node3>
</node2>
</node1>
Что мне нужно, так это создать, скажем, текстовое поле с именем node1__node2__node3
Что я делал до сих пор, так это
<input type="text" name="node1__
node2__
node3__"
Но то, что я хочу, это:
<input type="text" name="node1__node2__node3__"/>
Так что это бесполезно. Мой xslt для создания этого бесполезного вывода:
<xsl:template name="chooseNameID">
<xsl:param name="currentNode"/><!-- in this case currentNode is node3 -->
<xsl:variable name="fieldNames">
<xsl:for-each select="$currentNode/ancestor::*">
<xsl:value-of select="name(.)"/>__
</xsl:for-each>
</xsl:variable>
<xsl:attribute name="name">
<xsl:value-of select="$fieldNames"/>
</xsl:attribute>
</xsl:template>
Я предполагаю, что проблема в <xsl:value-of
, но я не могу найти никакого решения для этого.
Спасибо
Комментарии:
1. Хороший вопрос, 1. Смотрите мой ответ для полного, короткого и простого решения. 🙂
Ответ №1:
Это преобразование:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node3">
<xsl:variable name="vName">
<xsl:for-each select=
"ancestor-or-self::*[not(position()=last())]">
<xsl:value-of select="name()"/>
<xsl:if test="not(position()=last())">__</xsl:if>
</xsl:for-each>
</xsl:variable>
<input type="text" name="{$vName}"/>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному XML-документу:
<root>
<node1>
<node2>
<node3>Data</node3>
</node2>
</node1>
</root>
выдает желаемый, правильный результат:
<input type="text" name="node1__node2__node3"/>
Обратите внимание: использование AVT (шаблон значения атрибута) для генерации требуемого вывода в одной короткой строке.
Ответ №2:
Нежелательные пробелы, включая новые строки, являются частью литерала текстового узла в цикле.
В документе таблицы стилей текстовые узлы, содержащие только пробелы, игнорируются за исключением внутри xsl:text
. Однако пробелы, расположенные рядом с другим текстом, являются частью этого текста.
Буквенными пробелами в таблице стилей можно управлять с помощью xsl:text
.
<!-- change this -->
<xsl:for-each select="$currentNode/ancestor::*">
<xsl:value-of select="name(.)"/>__
</xsl:for-each>
<!-- to this -->
<xsl:for-each select="$currentNode/ancestor::*">
<xsl:value-of select="name(.)"/>__<xsl:text/>
</xsl:for-each>
<!-- or this -->
<xsl:for-each select="$currentNode/ancestor::*">
<xsl:value-of select="name(.)"/>
<xsl:text>__</xsl:text>
</xsl:for-each>
Ответ №3:
Как обычно, задав вопрос, вы находите решение.
Изменение <xsl:value-of select="$fieldNames"/>
строки с помощью этого <xsl:value-of select="normalize-space($fieldNames)"
сработало для меня.
Комментарии:
1. В результате все равно останутся пробелы, поскольку normalize-space() заменит каждую внутреннюю последовательность пробелов одним пробелом.