2014-10-01 135 views
1

我需要編寫一個擴展的XSLT,它不會輸出(刪除)任何空的元素。對於屬性,這意味着如果路徑的值爲空,則不會在輸出中填充該屬性。對於節點,這意味着如果沒有任何數據(空屬性或沒有屬性/數據的子節點),它不會在輸出中填充該節點。下面是一個關於棒球的例子,以更好地解釋我在找什麼。XSL在轉換後刪除空元素

輸出如何看起來像現在:

<Baseball> 
    <Fields> 
     <Equipment> 
     <Bats> 
      <Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite" /> 
      <Bat Brand="Easton" Model="asdfer" Length="32" Weight="29" Description="" /> 
      <Bat Brand="" Model="" Length="" Weight="" Description="" /> 
     </Bats> 
     <Gloves> 
      <Glove Brand="" Model="" Length="" Description="" /> 
     </Gloves> 
     </Equipment> 
    </Fields> 
    </Baseball> 

如何需要輸出的樣子:

<Baseball> 
    <Fields> 
     <Equipment> 
     <Bats> 
      <Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite" /> 
      <Bat Brand="Easton" Model="asdfer" Length="32" Weight="29" /> 
     </Bats> 
     </Equipment> 
    </Fields> 
    </Baseball> 

我知道我可以通過寫檢查值解決這個問題,但考慮到如果可能的話,我想盡量避免這種情況。另外,給出我將繪製的XML的結構,給定輸出節點的屬性將具有彼此區分的路徑。例如,輸出節點「Bat」中的屬性「Brand」可能具有「ab/cd/ef/brand」的路徑,而屬性「Model」可能具有路徑「ab/wx/yz/model」。 (我知道我上面的棒球例子不利於這一點)。有沒有辦法做到這一點,而不寫兩個XSLT?您可以通過XSLT中的輸出回傳嗎?

+1

沒辦法做了第二次與單一變換,但你可以寫你的XSLT來應付這個問題在一個整潔的方式...你有沒有輸入的例子XML,所以我們可以證明? – JohnLBevan 2014-10-01 00:46:38

+0

@JohnLBevan「*沒有辦法做第二次通過一個單一的變換*」不知道你是什麼意思。你當然可以**在相同的轉換(樣式表)中進行多次傳遞。你會發現很多這樣的例子,這是我選擇的第一個例子:http://stackoverflow.com/questions/24205393/distinct-values-with-xslt-1-0-when-xpath-has-multiple-criteria/ 24216212#24216212 – 2014-10-01 05:08:40

+0

@ michael.hor257k - 在顯示的示例中沒有多個文檔傳遞。數據被加載到一個被操作的變量中,但是沒有一些模板設置可以匹配由原始文檔上匹配的不同模板生成的元素。 – JohnLBevan 2014-10-01 10:40:47

回答

1

也許測試後代屬性的字符串長度?像這樣:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     version="1.0"> 
     <xsl:template match="*"> 
      <xsl:choose> 
       <xsl:when test="count(descendant-or-self::*/@*) > 0"> 
        <xsl:if test="string-length(descendant-or-self::*/@*) > 0"> 
         <xsl:copy> 
          <xsl:apply-templates select="@*|node()"/> 
         </xsl:copy> 
        </xsl:if> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:copy> 
         <xsl:apply-templates select="@*|node()"/> 
        </xsl:copy>  
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:template> 
     <xsl:template match="@*"> 
      <xsl:if test="string-length(.) > 0"> 
       <xsl:copy/> 
      </xsl:if> 
     </xsl:template> 
    </xsl:stylesheet> 

注意:這隻測試屬性的內容的長度,而不是實際的節點文本。樣本中沒有任何內容,您可以擴展測試。

3

爲了實現您的目標,不需要製作兩個通行證。您只需將模板添加到現有的樣式表中,以匹配不攜帶信息的節點並壓制它們。

既然你已經不是我們展示了您現有的樣式表,下面的示例僅適用的恆等變換的輸入爲默認值,而另外兩個模板,消除空節點/分支:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

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

<!-- prune the tree -->  
<xsl:template match="*[not(descendant::text() or descendant-or-self::*/@*[string()])]"/> 
<xsl:template match="@*[not(string())]"/> 

</xsl:stylesheet> 

應用您當前的輸出作爲測試輸入,結果將是:

<?xml version="1.0" encoding="UTF-8"?> 
<Baseball> 
    <Fields> 
     <Equipment> 
     <Bats> 
      <Bat Brand="Louisville" Model="16534" Length="34" Weight="30" Description="Composite"/> 
      <Bat Brand="Easton" Model="asdfer" Length="32" Weight="29"/> 
     </Bats> 
     </Equipment> 
    </Fields> 
</Baseball>