XML:
<root>
<item>
<key>mustBeSECONDKey</key>
<value>MustBeSECONDValue</value>
</item>
<item>
<key>mustBeFIRSTKey</key>
<value>MustBeFIRSTValue</value>
</item>
</root>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<file>
<xsl:for-each select="root/item">
<xsl:if test="key[text()='mustBeFIRSTKey']">
<xsl:element name="someCustomTagName">
<xsl:value-of select="value" />
</xsl:element>
</xsl:if>
</xsl:for-each>
<xsl:for-each select="root/item">
<xsl:if test="key[text()='mustBeSECONDKey']">
<xsl:element name="anotherNameOfATag">
<xsl:value-of select="value" />
</xsl:element>
</xsl:if>
</xsl:for-each>
</file>
</xsl:template>
</xsl:stylesheet>
出力:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<file>
<someCustomTagName>MustBeFIRSTValue</someCustomTagName>
<anotherNameOfATag>MustBeSECONDValue</anotherNameOfATag>
</file>
ここでの考え方は、指定した順序でタグが出力ドキュメントに収まるようにすることです。だから私は基本的に「すべてを調べて最初のものを見つけ、次にすべてを調べて2番目のものを見つける」と言うことでそれをやっています。これは明らかに機能します。
ただし、これがこの質問の核心になりますが、この目標を達成するためのより効率的な方法 (おそらく複数の方法) が必要だと思います。それは何ですか?
そしてさらにしわがあります。にとmustBeFIRSTKey
の 2 つの可能な値があるMustBeFIRSTValueUno
としMustBeFIRSTValueNi
ます。次に、これら 2 つの値を別の 2 つの値のセットGazpacho
およびSushi
にそれぞれマップします。そう
<item>
<key>mustBeFIRSTKey</key>
<value>MustBeFIRSTValueNi</value>
</item>
になる
<mustBeFIRSTKey>Sushi</mustBeFIRSTKey>
編集:私の問題は、ほとんど Java 側を見た概念的な問題であることがわかりました。私のセットアップ中にTransformer
私はこれをやっていました:
StreamSource xsltSource = new StreamSource(ClassLoader.getSystemResourceAsStream(transformLocation));
私はこれをしていたはずです:
StreamSource xsltSource = new StreamSource(ClassLoader.getSystemResource(transformLocation).toString());
そのStreamSource
コンストラクターは を設定しますsystemId
。これにより、次のように @Ian_Robert のより賢いソリューションを以下から使用できます。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- I discovered I could merge the $map and $inlineMap variables. -->
<xsl:variable name="inlineMap" select="document('')//xsl:variable[@name = 'inlineMap']/map">
<map>
<key from="mustBeFIRSTKey" to="someCustomTagName" />
<key from="mustBeSECONDKey" to="anotherNameOfATag">
<value from="MustBeSECONDValueUno" to="Gazpacho" />
<value from="MustBeSECONDValueNi" to="Sushi" />
</key>
</map>
</xsl:variable>
<xsl:key name="valueMap" match="value" use="concat(../@from, '|', @from)" />
<xsl:template match="root">
<xsl:variable name="items" select="item" />
<file>
<xsl:for-each select="$inlineMap">
<xsl:for-each select="key">
<xsl:apply-templates select="$items[key = current()/@from]">
<xsl:with-param name="elementName" select="@to"/>
</xsl:apply-templates>
</xsl:for-each>
</xsl:for-each>
</file>
</xsl:template>
<xsl:template match="item">
<xsl:param name="elementName" />
<xsl:variable name="currentItem" select="." />
<xsl:element name="{$elementName}">
<xsl:for-each select="$inlineMap">
<xsl:variable name="value" select="key('valueMap', concat($currentItem/key, '|', $currentItem/value))" />
<xsl:choose>
<xsl:when test="$value">
<xsl:value-of select="$value/@to" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$currentItem/value" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
この例では、マッピングなしで値を処理するためのロジックを取り除いています。