鑑於這種源文件:這種合併和重複數據刪除方法有什麼問題?
<?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>
和參數是可用的環境,我想有一個合併和重複數據刪除節點集結束了,保持最具體的值之一。所以,對於「刺」:
<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中使用的鍵,我想出了這個樣式表,對於「刺」的作品,而不是「開發」或' 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()
節點進行重複的項目的節點集,但與「開發」或「質量保證」跑,我得到如下:
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>
的位置,我選擇物?具體而言,爲什麼它只能在最後的位置工作,我如何使它適用於任何位置?
編輯1
當我隔離$all-items
數據(對於任何環境),並把它放在它自己的文件,該XSL正常工作。下面的例子是全局的工會和 '開發':
<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
?
謝謝。
我無法在組匹配謂詞中使用'$ environment'運行樣式表:'XPath錯誤:未定義變量 編譯錯誤:文件config4.xsl第13行元素模板 未能編譯謂詞'匹配= 「組[@名稱= $環境]」'。這確實符合所提供的來源。謝謝。 – 2012-01-16 22:26:12
@Zachary年輕 - 嗯......我用薩克森-H和Xalan測試過,沒什麼問題。我會看看xsltproc。 – 2012-01-16 22:28:52
@ZacharyYoung - 撒克遜6.5.5也失敗了。我更新了樣式表以使用xsl:if代替謂詞中的變量。 – 2012-01-16 22:32:32