Cra*_*aig 29 xslt concatenation
我需要使用XSLT构建一个字符串,并用逗号分隔每个字符串,但在最后一个字符串后不包含逗号.在下面的例子中,如果我有Distribution节点而不是Note节点,我将有一个尾随逗号.无论如何,我不知道将字符串构建为变量,然后截断XSLT中的最后一个字符.这也是使用Microsoft XSLT引擎.
我的字符串=
<xsl:if test="Locality != ''">
<xsl:value-of select="Locality"/>,
</xsl:if>
<xsl:if test="CollectorAndNumber != ''">
<xsl:value-of select="CollectorAndNumber"/>,
</xsl:if>
<xsl:if test="Institution != ''">
<xsl:value-of select="Institution"/>,
</xsl:if>
<xsl:if test="Distribution != ''">
<xsl:value-of select="Distribution"/>,
</xsl:if>
<xsl:if test="Note != ''">
<xsl:value-of select="Note"/>
</xsl:if>
Run Code Online (Sandbox Code Playgroud)
[男人必须有更好的方式进入这个问题文本框:(]
Dim*_*hev 51
使用XSLT很容易实现(无需在变量中捕获结果,或使用特殊的命名模板):
I. XSLT 1.0:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*/*">
<xsl:for-each select=
"Locality/text() | CollectorAndNumber/text()
| Institution/text() | Distribution/text()
| Note/text()
"
>
<xsl:value-of select="."/>
<xsl:if test="not(position() = last())">,</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
当此转换应用于以下XML文档时:
<root>
<record>
<Locality>Locality</Locality>
<CollectorAndNumber>CollectorAndNumber</CollectorAndNumber>
<Institution>Institution</Institution>
<Distribution>Distribution</Distribution>
<Note></Note>
<OtherStuff>Unimportant</OtherStuff>
</record>
</root>
Run Code Online (Sandbox Code Playgroud)
产生了想要的结果:
Locality,CollectorAndNumber,Institution,Distribution
Run Code Online (Sandbox Code Playgroud)
如果想要的元素不是按文档顺序生成的(问题中不需要,但是由Tomalak提出),实现这一点仍然非常容易和优雅:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:param name="porderedNames"
select="' CollectorAndNumber Locality Distribution Institution Note '"/>
<xsl:template match="/*/*">
<xsl:for-each select=
"*[contains($porderedNames, concat(' ',name(), ' '))]">
<xsl:sort data-type="number"
select="string-length(
substring-before($porderedNames,
concat(' ',name(), ' ')
)
)"/>
<xsl:value-of select="."/>
<xsl:if test="not(position() = last())">,</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
这里所需元素的名称及其所需顺序在string参数中提供,该参数$porderedNames包含所有需要名称的空格分隔列表.
当上述转换应用于同一XML文档时,生成所需结果:
CollectorAndNumber,Locality,Distribution,Institution
Run Code Online (Sandbox Code Playgroud)
II.XSLT 2.0:
在XSLT中,此任务更简单(同样,不需要特殊功能):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*/*">
<xsl:value-of separator="," select=
"(Locality, CollectorAndNumber,
Institution, Distribution,
Note)[text()]" />
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
将此转换应用于同一XML文档时,会生成相同的正确结果:
Locality,CollectorAndNumber,Institution,Distribution
Run Code Online (Sandbox Code Playgroud)
请注意,所需元素将按任何所需顺序生成,因为我们使用的是XPath 2.0序列类型(与XSLT 1.0解决方案中的union相比),根据定义,它包含任何所需(指定)顺序的项目.
我更喜欢一个简短的调用模板来将节点值连接在一起.如果Institution缺少连接列表中间的节点,这也适用:
<xsl:template name="join">
<xsl:param name="list" />
<xsl:param name="separator"/>
<xsl:for-each select="$list">
<xsl:value-of select="." />
<xsl:if test="position() != last()">
<xsl:value-of select="$separator" />
</xsl:if>
</xsl:for-each>
</xsl:template>
Run Code Online (Sandbox Code Playgroud)
这是一个如何使用它的简短示例:
<?xml version="1.0" encoding="utf-8"?>
<items>
<item>
<Locality>locality1</Locality>
<CollectorAndNumber>collectorAndNumber1</CollectorAndNumber>
<Distribution>distribution1</Distribution>
<Note>note1</Note>
</item>
<item>
<Locality>locality2</Locality>
<CollectorAndNumber>collectorAndNumber2</CollectorAndNumber>
<Institution>institution2</Institution>
<Distribution>distribution2</Distribution>
<Note>note2</Note>
</item>
<item>
<Locality>locality3</Locality>
<CollectorAndNumber>collectorAndNumber3</CollectorAndNumber>
<Institution>institution3</Institution>
<Distribution>distribution3</Distribution>
</item>
</items>
Run Code Online (Sandbox Code Playgroud)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<summary>
<xsl:apply-templates />
</summary>
</xsl:template>
<xsl:template match="item">
<item>
<xsl:call-template name="join">
<xsl:with-param name="list" select="Locality | CollectorAndNumber | Institution | Distribution | Note" />
<xsl:with-param name="separator" select="','" />
</xsl:call-template>
</item>
</xsl:template>
<xsl:template name="join">
<xsl:param name="list" />
<xsl:param name="separator"/>
<xsl:for-each select="$list">
<xsl:value-of select="." />
<xsl:if test="position() != last()">
<xsl:value-of select="$separator" />
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
<?xml version="1.0" encoding="utf-8"?>
<summary>
<item>locality1,collectorAndNumber1,distribution1,note1</item>
<item>locality2,collectorAndNumber2,institution2,distribution2,note2</item>
<item>locality3,collectorAndNumber3,institution3,distribution3</item>
</summary>
Run Code Online (Sandbox Code Playgroud)
注意:如果您使用的是XSLT/XPath 2.0,则会有fn:string-join
fn:string-join**($operand1 as string*, $operand2 as string*) as string
Run Code Online (Sandbox Code Playgroud)
可以使用如下:
fn:string-join({Locality, CollectorAndNumber, Distribution, Note}, ",")
Run Code Online (Sandbox Code Playgroud)