2013-04-09 64 views
1

我需要一些XSLT語句,它給了我一些像「LEFT JOIN」的內容:如果選擇的節點確實存在,則返回所有這些節點,否則返回一次。XSL for-each和LEFT JOIN

這與xsl:for-each循環不同,因爲當沒有這樣的節點時,for-each循環返回ZERO行。

這是一個實際的例子。

XML文件:

<root> 
    <sec1> 
     <x1/> ... <x1/> 
    </sec1> 
    <sec2> 
     <x2/> ... <x2/> 
    </sec2> 
    ... 
    <sec10> 
     <x10/> ... <x10/> 
    </sec10> 
</root> 

現在,我不知道有多少「X1」,「X2」,..「X10」我有,我想打印出所有可能的組合。一個簡單的和錯誤的解決辦法:

<xsl:for-each select="/root/sec1/x1"> 
    <xsl:for-each select="/root/sec2/x2"> 
     ... 
     <xsl:for-each select="/root/sec10/x10"> 
      ...print x1 and x2... and x10 
     </xsl:for-each> 
     ... 
    </xsl:for-each> 
</xsl:for-each> 

該解決方案是錯誤的,因爲,如果沒有「×3」則返回0行(就像一個FULL JOIN),而我希望看到所有其他值(如左或右連接)。

我可以結合使用xsl:choose,xls:when,xsl:foreach和xsl:否則這個時間很長。

我試圖建立自己的XSL模板,但它不工作:

<xsl:template name="left-join"> 
    <xsl:param name="select"/> 
    <xsl:param name="template"/> 

    <xsl:choose> 
     <xsl:when test="$select"> 
      <xsl:for-each select="$select"> 
       <xsl:call-template name="$templatename"> <!--WRONG --> 
        <xsl:with-param name="one-parameter" select="$select"/> 
       </xsl:call-template> 
      </xsl:for-each> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:call-template name="$templatename"> 
       <xsl:with-param name="one-parameter" select="$select"/> 
      </xsl:call-template> 
     </xsl:otherwise> 
    </xsl:choose> 
</xsl:template> 

回答

0

與嵌套這樣做的,似乎每一個十分錯誤的:它似乎是遞歸的候選人。但我很難理解問題的確切性質。每個x1,x2等出現(0或1)次?在這種情況下,問題肯定是微不足道的,你不需要for-each來迭代單例。

如果您想避免遞歸的條件代碼的冗長,那麼您應該轉移到XSLT 2.0。

+0

不,我不知道,X1,X2,...衝擊片雷管只有一次。他們可以出現任何次數。 XSLT 2.0可以獲得什麼? – user1922691 2013-04-09 15:03:59

1

即使我完全不瞭解你的問題,我會嘗試一個答案。 我的理解是,你正在鎖定的東西像一個SQL左連接。 (例如http://www.w3schools.com/sql/sql_join_left.asp) XML/XSLT版本可能如下。

輸入數據:

<root> 
     <Persons> 
      <Person id="1"> 
       <Name>Hansen</Name> 
      </Person> 
      <Person id="2"> 
       <Name>Svendson</Name> 
      </Person> 
      <Person id="3"> 
       <Name>Pettersen</Name> 
      </Person> 
     </Persons> 
     <Orders> 
      <Order id="1" > 
       <P_Id>3</P_Id> 
       <OrderNo>77895</OrderNo> 
      </Order> 
      <Order id="2"> 
       <P_Id>3</P_Id> 
       <OrderNo>44678</OrderNo> 
      </Order> 
      <Order id="3"> 
       <P_Id>1</P_Id> 
       <OrderNo>22456</OrderNo> 
      </Order> 
      <Order id="4"> 
       <P_Id>1</P_Id> 
       <OrderNo>24562</OrderNo> 
      </Order> 
      <Order id="5"> 
       <P_Id>15</P_Id> 
       <OrderNo>34764</OrderNo> 
      </Order> 
     </Orders> 
    </root> 

XSLT

<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="*"/> 

     <xsl:template match="root"> 
      <xsl:call-template name="person_order" /> 
     </xsl:template> 

     <xsl:template name="person_order"> 
      <orders> 
      <xsl:for-each select="//Person"> 
       <xsl:variable name ="pid" select="@id" /> 
       <xsl:call-template name="left_join"> 
        <xsl:with-param name="jname" select="'order'"/> 
        <xsl:with-param name="left" select="."/> 
        <xsl:with-param name="right" select="//Order[P_Id = $pid]"/> 
       </xsl:call-template> 
      </xsl:for-each> 
      </orders> 
     </xsl:template> 


     <xsl:template name="left_join"> 
      <xsl:param name="jname" /> 
      <xsl:param name="left" /> 
      <xsl:param name="right" /> 

      <xsl:choose> 
       <xsl:when test="$right"> 
        <xsl:for-each select="$right"> 
         <xsl:call-template name="print_join"> 
          <xsl:with-param name="jname" select="$jname"/> 
          <xsl:with-param name="left" select="$left"/> 
          <xsl:with-param name="right" select="."/> 
         </xsl:call-template> 
        </xsl:for-each> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:call-template name="print_join"> 
         <xsl:with-param name="jname" select="$jname"/> 
         <xsl:with-param name="left" select="$left"/> 

        </xsl:call-template> 
       </xsl:otherwise> 
      </xsl:choose> 

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

     <xsl:template name="print_join"> 
      <xsl:param name="jname" /> 
      <xsl:param name="left" /> 
      <xsl:param name="right" /> 
      <xsl:element name="{$jname}" > 
       <xsl:for-each select="$left"> 
        <xsl:apply-templates select="node() "/> 
       </xsl:for-each> 
       <xsl:if test="$right"> 
        <xsl:for-each select="$right"> 
         <xsl:apply-templates select="node() "/> 
        </xsl:for-each> 
       </xsl:if> 
      </xsl:element> 
     </xsl:template> 

    </xsl:stylesheet> 

產生輸出:

<orders> 
     <order> 
     <Name>Hansen</Name> 
     <P_Id>1</P_Id> 
     <OrderNo>22456</OrderNo> 
     </order> 
     <order> 
     <Name>Hansen</Name> 
     <P_Id>1</P_Id> 
     <OrderNo>24562</OrderNo> 
     </order> 
     <order> 
     <Name>Svendson</Name> 
     </order> 
     <order> 
     <Name>Pettersen</Name> 
     <P_Id>3</P_Id> 
     <OrderNo>77895</OrderNo> 
     </order> 
     <order> 
     <Name>Pettersen</Name> 
     <P_Id>3</P_Id> 
     <OrderNo>44678</OrderNo> 
     </order> 
    </orders>