2009-10-20 89 views
1

我試圖將XML文件的某些部分轉換爲另一個XML文件。源文件:XSLT:在該循環之外的循環內使用表達式的結果

<CUSTOMERS> 
    <CUSTOMER> 
    <CUSTOMER_NUMBER>12345678</CUSTOMER_NUMBER> 
    <CUSTOMER_ADDRESS> 
     <CUSTOMER_ADDRESS_NAME>John Doe</CUSTOMER_ADDRESS_NAME> 
     <CUSTOMER_ADDRESS_STREET>Street 1</CUSTOMER_ADDRESS_STREET> 
     <CUSTOMER_ADDRESS_CITY>Amsterdam</CUSTOMER_ADDRESS_CITY> 
    </CUSTOMER_ADDRESS> 
    <CUSTOM_FIELDS> 
     <CUSTOM_FIELD> 
     <CUSTOM_FIELD_NAME>Cellphone</CUSTOM_FIELD_NAME> 
     <CUSTOM_FIELD_VALUE>443209432</CUSTOM_FIELD_VALUE> 
     </CUSTOM_FIELD> 
     <CUSTOM_FIELD> 
     <CUSTOM_FIELD_NAME>Geo</CUSTOM_FIELD_NAME> 
     <CUSTOM_FIELD_VALUE>323932121,31231233,0</CUSTOM_FIELD_VALUE> 
     </CUSTOM_FIELD> 
    </CUSTOM_FIELDS> 
    </CUSTOMER> 
</CUSTOMERS> 

規則:

  • 不是每個CUSTOMERCUSTOM_FIELDS,那些沒有CUSTOM_FIELDS誰不應該被處理。
  • CUSTOMERCUSTOM_FIELDS時,所有CUSTOM_FIELDS的數量和順序可能會有所不同。如果它有一個CUSTOM_FIELD這名字是'Geo'

所以在我的XSL我試圖遍歷所有CUSTOMERS,以及通過CUSTOM_FIELDS每個CUSTOMER

  • 一個CUSTOMER只應處理。當它找到一個叫做'Geo'的應該輸出數據。

    <xsl:for-each select="CUSTOMERS/CUSTOMER"> 
        <xsl:for-each select="CUSTOM_FIELDS/CUSTOM_FIELD"> 
        <xsl:if test=".[CUSTOM_FIELD_NAME='Geo']"> 
         <Placemark> 
         <name> 
          <xsl:value-of select="CUSTOMER_NUMBER" /> 
          <xsl:text> </xsl:text> 
          <xsl:value-of select="CUSTOMER_ADDRESS/CUSTOMER_ADDRESS_NAME" /> 
         </name> 
         <styleUrl>#msn_ylw-pushpin</styleUrl> 
         <Point> 
          <coordinates> 
          <xsl:value-of select="CUSTOM_FIELD_NAME" /> 
          </coordinates> 
         </Point> 
         </Placemark> 
        </xsl:if> 
        </xsl:for-each> 
    </xsl:for-each> 
    

    當然在這一點上我在CUSTOMERS/CUSTOMER/CUSTOM_FIELDS/CUSTOM_FIELD,但因此它不可能從那些幾級了節點的輸出數據。

    我試着在if塊中設置一個變量,然後應該在if塊之後讀取以查看是否應該返回任何數據,但我知道變量只能設置一次,因此無法使用爲此目標。

    所以我的問題是:

    • 我真的需要一個循環,看看是否有CUSTOM_FIELD誰的CUSTOM_FIELD_NAME = 'Geo'
    • 如果需要循環,我如何使用循環內部,循環外部的結果?
    • 或者如果這是不可能的,我該如何從節點上的節點返回值,這些節點比我當前所在的節點高出幾級?
  • 回答

    2

    您的問題很容易用XPath解決。考慮這個解決方案:

    <xsl:stylesheet 
        version="1.0" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    > 
        <xsl:output method="xml" indent="yes" encoding="utf-8" /> 
    
        <xsl:template match="CUSTOMERS"> 
        <Placemarks> 
         <!-- apply templates to every customer --> 
         <xsl:apply-templates select="CUSTOMER" /> 
        </Placemarks> 
        </xsl:template> 
    
        <xsl:template match="CUSTOMER"> 
        <!-- process only customers that have a "Geo" custom field --> 
        <xsl:if test="CUSTOM_FIELDS/CUSTOM_FIELD[CUSTOM_FIELD_NAME = 'Geo']"> 
         <Placemark> 
         <name> 
          <xsl:value-of select="CUSTOMER_NUMBER"/> 
          <xsl:text> </xsl:text> 
          <xsl:value-of select="CUSTOMER_ADDRESS/CUSTOMER_ADDRESS_NAME"/> 
         </name> 
         <styleUrl> 
          <xsl:text>#msn_ylw-pushpin</xsl:text> 
         </styleUrl> 
         <Point> 
          <coordinates> 
          <xsl:value-of select=" 
           CUSTOM_FIELDS/CUSTOM_FIELD[ 
           CUSTOM_FIELD_NAME = 'Geo' 
           ]/CUSTOM_FIELD_VALUE 
          "/> 
          </coordinates> 
         </Point> 
         </Placemark> 
        </xsl:if> 
        </xsl:template> 
    
    </xsl:stylesheet> 
    

    第一個模板(match="CUSTOMERS")處理每個<CUSTOMER>節點。

    他們被交給第二個模板(match="CUSTOMER"),決定是否處理客戶。

    它通過檢查名稱爲'Geo'的自定義字段的存在來做到這一點。如果存在這樣的節點,則創建<Placemark>。上面的輸出是:

    <Placemarks> 
        <Placemark> 
        <name>12345678 John Doe</name> 
        <styleUrl>#msn_ylw-pushpin</styleUrl> 
        <Point> 
         <coordinates>323932121,31231233,0</coordinates> 
        </Point> 
        </Placemark> 
    </Placemarks> 
    

    所以沒有需要任何循環或廣泛的檢查,他們表明你是不是從XSLT的觀點看問題。;-)

    我們您的問題:

    [...]使其不能輸出從幾個 水平,直至節點 數據。

    當然這是 - 您可以隨時使用'..' XPath操作員或沿着軸移動ancestor::。我建議你先閱讀關於XPath的更多內容,你似乎很想念。

    我試過在 如果塊,那麼這應該 if區塊後讀,看是否有數據應 返回,但我明白變量 只能設置一次,所以設置一個變量他們也不能是用於此目標的 。

    變量不只是只讀的,如果處理流程離開其父元素,它們也會立即超出範圍。因此,檢查的變量內部的以外的if塊的變量 if-block無法開始。

    我真的需要一個循環來看看 有一個CUSTOM_FIELD誰的 CUSTOM_FIELD_NAME = 'Geo'

    不需要。您需要像上面顯示的XPath檢查。

    如果需要循環,我怎麼能使用 結果從內循環,外 循環?

    否如上所述。

    或者,如果這是不可能的,我怎麼能 從在節點之上的 幾級我 目前節點的返回值?

    上面還解釋過。 ;-)

    +0

    感謝您的正確答案,並深入解釋! 我知道必須有一種更有效的方法來實現這一點,但我發現的所有示例和文檔僅列出了非常簡單的案例。 無論如何,再次感謝:-) – Rene 2009-10-20 13:46:08

    +0

    不客氣。 :-) – Tomalak 2009-10-20 14:53:27