このソース ドキュメントを考えると:
<?xml version="1.0" encoding="utf-8"?>
<config>
<group name="global">
<globals>
<item grp="db" prop="userid" value="foo"/>
<item grp="db" prop="passwd" value="bar"/>
<item grp="log" prop="level" value="debug"/>
<item grp="log" prop="filename" value="red.log"/>
</globals>
</group>
<group name="dev">
<globals>
<item grp="db" prop="server" value="dev_sql_1"/>
</globals>
<locals>
<item grp="db" prop="catalog" value="red_db_local"/>
<item grp="db" prop="passwd" value="dev_passwd"/>
<item grp="log" prop="level" value="info"/>
</locals>
</group>
<group name="qa">
<globals>
<item grp="db" prop="server" value="qa_sql_1"/>
<item grp="db" prop="catalog" value="qa_db"/> <!-- this is wonky, but may happen -->
</globals>
<locals>
<item grp="db" prop="catalog" value="red_db_local"/> <!-- this should beat 'qa_db' from ../globals/item[@grp='db' and prop='catalog'] -->
<item grp="db" prop="passwd" value="qa_passwd"/>
<item grp="log" prop="level" value="critical"/>
</locals>
</group>
<group name="prod">
<globals>
<item grp="db" prop="server" value="prod_sql_1"/>
</globals>
<locals>
<item grp="db" prop="catalog" value="prod_db_local"/>
<item grp="db" prop="passwd" value="prod_passwd"/>
<item grp="log" prop="level" value="critical"/>
</locals>
</group>
</config>
および利用可能な環境の 1 つであるパラメーター、マージされて重複排除されたノードセットになり、最も具体的な値を保持したいと思います。したがって、「製品」の場合:
<config>
<item grp="db" prop="userid" value="foo"/>
<item grp="log" prop="filename" value="red.log"/>
<item grp="db" prop="server" value="prod_sql_1"/>
<item grp="db" prop="catalog" value="prod_db_local"/>
<item grp="db" prop="passwd" value="prod_passwd"/>
<item grp="log" prop="level" value="critical"/>
</config>
私は XSLT 1.0 でキーを使用するのが初めてで、'prod' では機能するが、'dev' や 'qa' では機能しないこのスタイルシートを思いつきました。
<?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" omit-xml-declaration="yes"/>
<xsl:param name="environment"/>
<!--
using | to create a union of top-level global items and and env-specific items
-->
<xsl:variable name="all-items"
select="/config/group[@name='global']/globals/item |
//group[@name=$environment]//item"/>
<xsl:key name="dupes" match="item" use="concat(@grp,'|',@prop)"/>
<xsl:template match="/config">
<xsl:copy>
<xsl:copy-of
select="$all-items[generate-id() = generate-id(key('dupes',
concat(@grp,'|',@prop))[last()])]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
これは私が目指しているアプローチです:
<item.../>
関連するすべてのノードを結合してノードセットにマージします|
- このノード セットを
@grp
および@prop
属性でグループ化します - 結果のグループのいずれかで最後のノードを保持します (重複除外)
私はキーに慣れていないので、このコードのビットを考えているとしか言えません。
<xsl:copy-of select="$all-items[generate-id() = generate-id(key('dupes',
concat(@grp,'|',@prop))[last()])]"/>
last()
重複アイテムのノードセットからノードを選択していますが、「dev」または「qa」で実行すると、次のようになります。
REG zacharyyoung$ xsltproc --stringparam environment dev config3.xsl config3.xml
<config>
<item grp="db" prop="userid" value="foo"/>
<item grp="log" prop="filename" value="red.log"/>
</config>
REG zacharyyoung$ xsltproc --stringparam environment qa config3.xsl config3.xml
<config>
<item grp="db" prop="userid" value="foo"/>
<item grp="log" prop="filename" value="red.log"/>
</config>
各環境パラメーターの中間変数all-items
を確認しましたが、少なくともそれだけは正しく機能しているようです。
<group name="qa"/>
下に移動すると、次のようになります。
<config>
<group name="global">...</group>
<group name="dev">...</group>
<group name="prod">...</group>
<group name="qa">...</group>
<config>
次に、「qa」で実行すると動作します:
REG zacharyyoung$ xsltproc --stringparam environment qa config3.xsl config3.xml
<config>
<item grp="db" prop="userid" value="foo"/>
<item grp="log" prop="filename" value="red.log"/>
<item grp="db" prop="server" value="qa_sql_1"/>
<item grp="db" prop="catalog" value="red_db_local"/>
<item grp="db" prop="passwd" value="qa_passwd"/>
<item grp="log" prop="level" value="critical"/>
</config>
では、なぜ<group name="...">...</group>
I'm selection の位置が重要なのでしょうか? 具体的には、最後の位置でしか機能しないのはなぜですか?また、どの位置でも機能させるにはどうすればよいですか?
編集1
$all-items
(任意の環境で)データを分離して独自のファイルに入れると、XSL は正しく機能します。次の例は、グローバルと「dev」の結合です。
<config>
<item grp="db" prop="userid" value="foo"/>
<item grp="db" prop="passwd" value="bar"/>
<item grp="log" prop="level" value="debug"/>
<item grp="log" prop="filename" value="red.log"/>
<item grp="db" prop="server" value="dev_sql_1"/>
<item grp="db" prop="catalog" value="red_db_local"/>
<item grp="db" prop="passwd" value="dev_passwd"/>
<item grp="log" prop="level" value="info"/>
</config>
そしてこのXSL:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="dupes" match="item" use="concat(@grp,'|',@prop)"/>
<xsl:template match="/config">
<xsl:copy>
<xsl:copy-of
select="item[generate-id() = generate-id(key('dupes',
concat(@grp,'|',@prop))[last()])]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
結果:
REG zacharyyoung$ xsltproc config4.xsl config4.xml
<config>
<item grp="db" prop="userid" value="foo"/>
<item grp="log" prop="filename" value="red.log"/>
<item grp="db" prop="server" value="dev_sql_1"/>
<item grp="db" prop="catalog" value="red_db_local"/>
<item grp="db" prop="passwd" value="dev_passwd"/>
<item grp="log" prop="level" value="info"/>
</config>
それで、今は変数に落ちているように見えますall-items
か?
ありがとうございました。