以微弱的嘗試澄清編輯。系統通過XSL處理器將XML轉換爲另一個XML。XSL:是否有使用謂詞變量的快速替代方法?
我正在爲有插卡的機器做一些XSL規則的東西。這些卡片將自己的XSL規則提供給主要主機,然後將這些規則集成到一個超級XSL文件中,以便自己處理,並且還將這些文件發送到HTTP'd到機器上的Web瀏覽器。瀏覽器用於設置機器的配置項目,XSL用於更改和/或隱藏和/或取消隱藏某些XML。爲了簡化我的查詢,我發明了一個小例子。
當用戶將項目配置爲B類型(可選擇幾個如A,B,C,...)時,接下來的兩個項目也將被更改(以某種方式)。在真實交易中,有一個屬性「隱藏」設置爲true或false,並且還設置了子元素。真實情況中的下兩個項目將被隱藏,並且子元素也會被更改。
當用戶將項目從類型B更改爲類型A時,我需要確定哪些其他節點需要將其「隱藏」屬性設置爲false。用戶會根據他們認爲合適的方式更改子元素。
所有這些都是「循環」,並且是有序的,所以如果一個節點被設置爲B類型,並且它是最後一個節點(沒有下一個兄弟節點),那麼受影響的節點是該集合中的第一個節點。 (在XPath術語中,如果節點[4]是類型B,則節點[1]和[2]將被隱藏並更改)。
所以,在這裏我的例子,我有作爲輸入XML:
<topline>
<midline type="A" name="mid1" hidden="false"><source name="off"/></midline>
<midline type="B" name="mid2" hidden="false"><source name="input 1"/></midline>
<midline type="A" name="mid3" hidden="false"><source name="off"/></midline>
<midline type="A" name="mid4" hidden="false"><source name="off"/></midline>
</topline>
和XSL將其更改爲:
<topline>
<midline type="A" name="mid1" hidden="false"><source name="off"/></midline>
<midline type="B" name="mid2" hidden="false"><source name="input 1"/></midline>
<midline type="A" name="mid3" hidden="true"><source name="input 1"/></midline>
<midline type="A" name="mid4" hidden="true"><source name="input 1"/></midline>
</topline>
現在,如果用戶改變了主意,並改變mid2成爲A型:
<topline>
<midline type="A" name="mid1" hidden="false"><source name="off"/></midline>
<midline type="A" name="mid2" hidden="false"><source name="input 1"/></midline>
<midline type="A" name="mid3" hidden="true"><source name="input 1"/></midline>
<midline type="A" name="mid4" hidden="true"><source name="input 1"/></midline>
</topline>
那麼XSL將取消隱藏mid2的兄弟姐妹之後的通告,所以結果壽ld是:
<topline>
<midline type="A" name="mid1" hidden="false"><source name="off"/></midline>
<midline type="A" name="mid2" hidden="false"><source name="input 1"/></midline>
<midline type="A" name="mid3" hidden="false"><source name="input 1"/></midline>
<midline type="A" name="mid4" hidden="false"><source name="input 1"/></midline>
</topline>
這是我正在努力的第二步。我所做的解決這個問題對我來說是相當難看的,但也許是不可避免的,因爲我試圖實現的並不是真正的XSL友好。
我已經登陸了做:
<xsl:for-each select="topline">
<xsl:for-each select="midline">
<xsl:variable name="masterPosition" select="position()"/>
<xsl:choose>
<xsl:when test="@type='B'>
hide the next two nodes. This is easy:
translate($masterPosition, '1234', '2341')
works nicely.
</xsl:when>
<xsl:otherwise>
<xsl:variable name="prior1" select="translate(masterPosition, '1234', '4123')"/>
<xsl:variable name="test1" select="../midline[$prior1]/source[1]/@name='off'"/>
this second line doesn't work: I only get the first node, always.
So instead I have
<xsl:variable name="test2">
<xsl:choice>
<xsl:when test="$masterPosition='1'"><xsl:value-of select="../midline[4]/source"/></xsl:when>
and so on for the other masterPositions
</xsl:choice>
</xsl:variable>
and this is repeated for a few other variables, one each for each relevant
prior position and for the fields I need to change. I then use these
variables to change the XML - there's something in the main machine's
processing to enable this, I believe it is non-standard, so please ignore:
(At least it doesn't run against Xalan).
<set key={$test2}/@hidden, value="false")/>
</xsl:otherwise>
</xsl:choose>
<xsl:for-each>
</xsl:for-each>
是否有這樣做,你能想到的更優雅的方式?如果沒有,不要擔心,我相信我的黑客會起作用,也不應該消耗太多的MIPS。
我無法使用<xsl:key>
,因爲我們的系統無法應對:我們有多個XSL源代碼被合成爲一個,並且代謝腳本(無法控制)根本不理解<xsl:key>
,所以如果有一個使用鍵的解決方案,我無法使用它。
感謝 理查德
您需要確保將所有標記正確標記爲降價編輯器中的代碼。看起來在「我想做什麼」中有一些標籤丟失,至少我沒有得到你想要達到的。 – Lucero 2010-12-03 10:54:49
這很奇怪。格式不是很好,但(對我來說,但後來我寫了它)似乎足夠清晰:比較第一個XML和第二個:源名稱更改爲「mid1」和「mid4」,因爲它們以循環方式,「mid2」。我需要一種方法來告訴節點「mid4」,確定它是否與「mid2」有關,因爲當處理「mid2」時,它改變了「mid4」。如果是這樣的話,我就把它放在一邊,否則我還有其他的事情需要我去做(「這是mid4作爲我的例子)。我希望這有助於,這聽起來有點漫不經心:-) – Richard 2010-12-03 11:01:42
好問題,+1。請參閱我的答案,以獲得從B型到A型逆轉的完整解決方案。 :) – 2010-12-03 14:45:09