2010-08-10 68 views
1

所以,我有我的手一個非常混亂的問題..XPath的結果是不正確的 - 通過整個XML不會

它使用XPath時,彷彿整個XML數據的層次結構不被搜索過在XSL中表達。

一些虛設XML數據:

<pets name="myPets" NUM="2"> 
    <dog name="allMyDogs" NUM="5"> 
     <dog name="Frank" NUM="3"/> 
     <dog name="Spot" NUM="4"/> 
     <dog name="Rover" NUM="1"/> 
     <dog name="Rupert" NUM="6"/> 
     <cat name="Lucy" NUM="4"/> 
    </dog> 
    <cat name="allMyCats" NUM="4"> 
     <cat name="Simba" NUM="4"/> 
     <cat name="Princess" NUM="5"/> 
     <cat name="Fluffy" NUM="1"/> 
     <cat name="Lucy" NUM="3"/> 
     <cat name="Lucy" NUM="35"/> 
     <cat name="Lucy" NUM="6"/> 
     <cat name="Lucy" NUM="1"/> 
    </cat> 
    <cat name="Lucy" NUM="9"/> 
</pets> 

以下是我相信是造成問題的的XSLT代碼部分:

<xsl:key name="elem_key" match="elem" use="concat(@key, .)" /> 

    <xsl:variable name="all_data"> 
    <xsl:apply-templates select="*"> 
     <xsl:sort select="name()" /> 
    </xsl:apply-templates> 
    </xsl:variable> 

    <xsl:template match="//*[@NUM&lt;=4]"> 
    <elem key="{name()}"> 
     <xsl:copy-of select="@*" /> 
     <xsl:for-each select="@*"> 
     <xsl:sort select="name()" /> 
     <attribute>|<xsl:value-of select="name()" />|</attribute> 
     </xsl:for-each> 
    </elem> 
    </xsl:template> 

    <xsl:template match="/"> 
    <html> 
     <body> 
     <xsl:for-each select="msxsl:node-set($all_data)"> 
       <xsl:for-each select="*[generate-id()=generate-id(key('elem_key',concat(@key, .))[1])]"> 
       <table > 
        <tr> 
        <td>Element Name</td> 
        <xsl:for-each select="*"> 
         <td> 
         <xsl:value-of select="translate(.,'|','')" /> 
         </td> 
        </xsl:for-each> 
        </tr> 
        <xsl:for-each select="key('elem_key', concat(@key, .))"> 
        <xsl:variable name="curr_elem" select="." /> 
        <tr> 
         <td> 
         <xsl:value-of select="@key" /> 
         </td> 
         <xsl:for-each select="*"> 
         <td > 
          <xsl:value-of select="$curr_elem/@*[name()=translate(current(),'|','')]" /> 
         </td> 
         </xsl:for-each> 
        </tr> 
        </xsl:for-each> 
       </table> 
       <p /> 
       </xsl:for-each> 
     </xsl:for-each> 
     </body> 
    </html> 
    </xsl:template> 

中的XPath表達式中使用:

//*[@NUM&lt;=4] 

(以上應該產生許多成果)

不正確的結果我得到:

Element Name name  NUM 
pets   myPets 2 

正如你可以看到它似乎停止在根。

如果我改變XPath來:

//*[@NUM=4] 

我得到這些不正確的結果:

Element Name name NUM 
dog  Spot  4 


Element Name name  NUM 
cat  Lucy  4 


Element Name name  NUM 
cat  allMyCats 4 

事情似乎發生的是,它會停止搜索分解成層次結構一旦找到了比賽。前兩個(Spot和Lucy)是正確的,但是當allMyCats(Simba)的子節點的NUM爲4時,它停在所有MyCats上。

任何人都可以幫助我修復此代碼,以便它返回正確的結果?我很沮喪! :(

謝謝!

+0

沒有完整的樣式表,我只能猜測...如果var'all_data'被聲明爲樣式表的頂層元素,那麼我建議在'xsl:apply-templates'中使用絕對路徑,如「/ *」 – 2010-08-10 17:30:01

+0

@ Alejandro:是樣式表中的第一個元素,然後是var all_data。我試過路徑「/ *」,但它不影響我的結果。 :( – developer 2010-08-10 18:20:57

+0

好問題(+1)。請參閱我的回答以解釋問題並獲得簡單的解決方案。:) – 2010-08-10 20:42:42

回答

3

只要改變

<xsl:variable name="all_data"> 
    <xsl:apply-templates select="*"> 
     <xsl:sort select="name()" /> 
    </xsl:apply-templates> 
    </xsl:variable> 

<xsl:variable name="all_data"> 
    <xsl:apply-templates select="*/*"> 
     <xsl:sort select="name()" /> 
    </xsl:apply-templates> 
    </xsl:variable> 

第一(許多的)問題是

<xsl:apply-templates select="*"> 

選擇當前節點的所有子元素。當前節點是/,它有只有一個孩子 - 頂級元素pets

實際上,你要收集的數據爲pets所有兒童。

還有其他問題,但我沒有空間和時間在這裏解決它們。

完整校正代碼如下

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
version="1.0"> 

<xsl:key name="elem_key" match="elem" 
     use="concat(@key, .)" /> 

    <xsl:variable name="all_data"> 
    <xsl:apply-templates select="*//*"> 
     <xsl:sort select="name()" /> 
    </xsl:apply-templates> 
    </xsl:variable> 

    <xsl:template match="*[@NUM&lt;=4]"> 
    <elem key="{name()}"> 
     <xsl:copy-of select="@*" /> 
     <xsl:for-each select="@*"> 
     <xsl:sort select="name()" /> 
     <attribute>|<xsl:value-of 
      select="concat(name(),'=',.)" />|</attribute> 
     </xsl:for-each> 
    </elem> 
    </xsl:template> 

    <xsl:template match="/"> 
    <html> 
     <body> 
     <xsl:for-each select="msxsl:node-set($all_data)"> 
       <xsl:for-each select= 
       "*[generate-id() 
       = 
        generate-id(key('elem_key',concat(@key, .))[1]) 
       ]"> 
       <table > 
        <tr> 
        <td>Element Name</td> 
        <xsl:for-each select="*"> 
         <td> 
         <xsl:value-of select= 
          "substring-before(translate(.,'|',''),'=')" /> 
         </td> 
        </xsl:for-each> 
        </tr> 
        <tr> 
         <td> 
         <xsl:value-of select="@key" /> 
         </td> 
         <xsl:for-each select="*"> 
         <td> 
          <xsl:value-of select= 
          "substring-after 
           (translate(current(),'|',''), 
           '=' 
           )"/> 
         </td> 
         </xsl:for-each> 
        </tr> 
       </table> 
       <p /> 
       </xsl:for-each> 
     </xsl:for-each> 
     </body> 
    </html> 
    </xsl:template> 
</xsl:stylesheet> 

當這個變換所提供的XML文檔施加:

<pets name="myPets" NUM="2"> 
    <dog name="allMyDogs" NUM="5"> 
     <dog name="Frank" NUM="3"/> 
     <dog name="Spot" NUM="4"/> 
     <dog name="Rover" NUM="1"/> 
     <dog name="Rupert" NUM="6"/> 
     <cat name="Lucy" NUM="4"/> 
    </dog> 
    <cat name="allMyCats" NUM="4"> 
     <cat name="Simba" NUM="4"/> 
     <cat name="Princess" NUM="5"/> 
     <cat name="Fluffy" NUM="1"/> 
     <cat name="Lucy" NUM="3"/> 
     <cat name="Lucy" NUM="35"/> 
     <cat name="Lucy" NUM="6"/> 
     <cat name="Lucy" NUM="1"/> 
    </cat> 
    <cat name="Lucy" NUM="9"/> 
</pets> 

有用結果(多隻動物)產生

<html xmlns:msxsl="urn:schemas-microsoft-com:xslt"> 
    <body> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>Lucy</td> 
       <td>4</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>allMyCats</td> 
       <td>4</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>Simba</td> 
       <td>4</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>Fluffy</td> 
       <td>1</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>Lucy</td> 
       <td>3</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>cat</td> 
       <td>Lucy</td> 
       <td>1</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>dog</td> 
       <td>Frank</td> 
       <td>3</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>dog</td> 
       <td>Spot</td> 
       <td>4</td> 
      </tr> 
     </table> 
     <p></p> 
     <table> 
      <tr> 
       <td>Element Name</td> 
       <td>name</td> 
       <td>NUM</td> 
      </tr> 
      <tr> 
       <td>dog</td> 
       <td>Rover</td> 
       <td>1</td> 
      </tr> 
     </table> 
     <p></p> 
    </body> 
</html> 
+0

@Dimitre:我用// * [@NUM = 4]和// * [@ NUM < = 4]但我仍然沒有得到「allMyCats」下的任何孩子 – developer 2010-08-10 21:02:57

+0

@iHeartGreek:然後您使用不同的代碼或XML文件。我編輯了我的回覆,並將完整的轉換,XML文件和結果放在那裏。您應該能夠複製它們並從轉換中獲得相同的結果。 – 2010-08-10 21:46:04

+0

@Dimitre:對於代碼中顯示的// * [@ NUM < = 4] ..我不希望讓名爲Fluffy和Simba的貓回來嗎?哦,露西NUM = 3和露西NUM = 1也從你的結果中缺失。我很抱歉,但我沒有收到與此代碼(確切的複製粘貼)正確的結果:(我在泡菜 – developer 2010-08-10 22:00:41

0

*[generate-id()=generate-id(key('elem_key',concat(@key, .))[1])]您已經鑰匙做一個匹配少數情況下選擇,然後你問的只是先用[1]

我什麼不清楚你是想爲正確的結果佈局進一步建議