これは、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>
この変換が次の XML ドキュメントに適用された場合:
<root>
<record>
<Locality>Locality</Locality>
<CollectorAndNumber>CollectorAndNumber</CollectorAndNumber>
<Institution>Institution</Institution>
<Distribution>Distribution</Distribution>
<Note></Note>
<OtherStuff>Unimportant</OtherStuff>
</record>
</root>
必要な結果が生成されます:
Locality,CollectorAndNumber,Institution,Distribution
必要な要素をドキュメントの順序ではなく生成する必要がある場合 (質問では必須ではありませんが、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>
ここでは、必要な要素の名前とそれらの必要な順序が文字列パラメーター$porderedNames
で提供されます。これには、必要なすべての名前のスペース区切りのリストが含まれます。
上記の変換が同じ XML ドキュメントに適用されると、必要な結果が生成されます。
CollectorAndNumber,Locality,Distribution,Institution
Ⅱ.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>
この変換を同じ XML ドキュメントに適用すると、同じ正しい結果が生成されます。
Locality,CollectorAndNumber,Institution,Distribution
XPath 2.0 シーケンス タイプ (XSLT 1.0 ソリューションのユニオンとは対照的) を使用しているため、必要な要素は任意の順序で生成されることに注意してください。