2014-10-01 62 views
0

我正在處理此處理指令:<?Pub _kern Amount="-25pt"?>檢查是否存在處理指令的容器元素

有:

<xsl:template match="processing-instruction('Pub')"> 
     <xsl:choose> 
      <xsl:when test="starts-with(., '_kern')"> 
       <xsl:attribute name="style"><xsl:text>padding-left: </xsl:text> 
       <xsl:value-of select="if (contains(.,'Amount')) then (substring-before(substring-after(., 'Amount=&quot;'), '&quot;')) else '12pt'"/> 
       </xsl:attribute> 
      </xsl:when> 
     </xsl:choose> 
</xsl:template> 

,但是這隻能當PI是一個容器元素中像<div>,等我由於XSLT試圖將樣式標籤添加到不存在的父元素,因此收到錯誤。如果我在<xsl:attribute name="style">之前包含<span>,那麼當PI位於容器元素中時,代碼不起作用。我怎樣才能檢測是否有一個容器元素,所以我知道是否要添加一個跨度?除非有更好的方法來做到這一點,否則我是XSLT的初學者。

回答

0

您可以檢查處理指令通過增加一個簡單的條件

<xsl:template match="processing-instruction('Pub')[parent::*]"> 

警惕不過,如果你的XML看起來像這樣有一個父元素:

<div> 
    <?Pub _kern Amount="-25pt"?>  
</div> 

你仍然可以得到一個如果空白文本節點先被匹配並複製,則會出錯。您可能需要在您的XSLT中包含xsl:strip-space命令。

例如,這會得到一個錯誤

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="processing-instruction('Pub')[parent::*]"> 
      <xsl:choose> 
       <xsl:when test="starts-with(., '_kern')"> 
        <xsl:attribute name="style"><xsl:text>padding-left: </xsl:text> 
        <xsl:value-of select="if (contains(.,'Amount')) then (substring-before(substring-after(., 'Amount=&quot;'), '&quot;')) else '12pt'"/> 
        </xsl:attribute> 
       </xsl:when> 
      </xsl:choose> 
    </xsl:template> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

但這並不....

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:strip-space elements="*" /> 

    <xsl:template match="processing-instruction('Pub')[parent::*]"> 
      <xsl:choose> 
       <xsl:when test="starts-with(., '_kern')"> 
        <xsl:attribute name="style"><xsl:text>padding-left: </xsl:text> 
        <xsl:value-of select="if (contains(.,'Amount')) then (substring-before(substring-after(., 'Amount=&quot;'), '&quot;')) else '12pt'"/> 
        </xsl:attribute> 
       </xsl:when> 
      </xsl:choose> 
    </xsl:template> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

編輯:在回答您的意見,即使你xsl:strip-space仍然得到一個錯誤如果在處理指令之前存在前兄弟姐妹

<div> 
    <text></text> 
    <?Pub _kern Amount="-25pt"?>  
</div> 

這是因爲e如果父節點已經有子節點輸出,則不能向父節點添加屬性。

如果目的是試圖將屬性添加到父那裏就可以了,但如果不創建span標記代替,那麼你可以更改模板的處理指令到該匹配的格式爲:

<xsl:template match="processing-instruction('Pub')"> 
    <xsl:choose> 
     <xsl:when test="not(parent::*) or preceding-sibling::node()"> 
      <span> 
       <!-- Add attribute --> 
      </span> 
     </xsl:when> 
     <xsl:otherwise> 
      <!-- Add attribute --> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

並且可以在模板中添加屬性以避免重複編碼。試試這個XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:strip-space elements="*" /> 

    <xsl:template match="processing-instruction('Pub')"> 
     <xsl:choose> 
      <xsl:when test="not(parent::*) or preceding-sibling::node()"> 
       <span> 
        <xsl:call-template name="processing-instruction"/> 
       </span> 
      </xsl:when> 
      <xsl:otherwise> 
       <xsl:call-template name="processing-instruction"/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

    <xsl:template name="processing-instruction"> 
     <xsl:choose> 
      <xsl:when test="starts-with(., '_kern')"> 
       <xsl:attribute name="style"><xsl:text>padding-left: </xsl:text> 
       <xsl:value-of select="if (contains(.,'Amount')) then (substring-before(substring-after(., 'Amount=&quot;'), '&quot;')) else '12pt'"/> 
       </xsl:attribute> 
      </xsl:when> 
     </xsl:choose> 
    </xsl:template> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 
+0

謝謝,@Tim C,但我仍然得到這個沒有跨度的錯誤:「一個屬性節點(樣式)不能在包含元素的子元素之後創建。」我在樣式表的頂部有''。 – Caroline 2014-10-01 19:00:35

+0

謝謝@Tim C,這對我有用。我感謝您花時間糾正我的錯誤。我還有其他處理指令,我忽略了它們的相關性,但我將它們添加到處理指令模板中。 – Caroline 2014-10-03 14:55:48

0

這個工作,我就不會沒有@Tim C'S幫助得到:

<xsl:template match="processing-instruction('Pub')"> 
    <xsl:choose> 
     <xsl:when test="starts-with(., '_kern') and processing-instruction()[parent::*]"> 
      <xsl:attribute name="style"><xsl:text>padding-left: </xsl:text> 
      <xsl:value-of select="if (contains(.,'Amount')) then (substring-before(substring-after(., 'Amount=&quot;'), '&quot;')) else '12pt'"/> 
      </xsl:attribute> 
     </xsl:when> 
     <xsl:when test="starts-with(., '_kern')"> 
      <span><xsl:attribute name="style"><xsl:text>padding-left: </xsl:text> 
      <xsl:value-of select="if (contains(.,'Amount')) then (substring-before(substring-after(., 'Amount=&quot;'), '&quot;')) else '12pt'"/> 
      </xsl:attribute></span> 
     </xsl:when> 
     <xsl:otherwise/> 
    </xsl:choose> 
</xsl:template> 

這也可能是不完全正確的,但它得到了這份工作完成。

+0

我認爲你的第一個'xsl:when'語句總是返回false,因爲你在'processing-instruction()[parent :: *]「>'的地方,這是尋找第二個處理指令,它是當前的處理指令,這是不可能的!你可以把它改成''但你可能會得到這個錯誤。在所有情況下輸出新的「span」最簡單嗎? – 2014-10-02 07:35:27

+0

我在這裏將它作爲不做的示例,我使用了@Tim C編輯的解決方案。 – Caroline 2014-10-03 14:56:14