2010-01-29 73 views
17

我正在嘗試編寫XSLT,它將在選定的後續兄弟上運行for-each,但在到達另一個標記(h1)時停止。XSLT:選擇以下兄弟直到達到指定的標記

這裏的源XML:

<?xml version="1.0"?> 
<html> 
    <h1>Test</h1> 
    <p>Test: p 1</p> 
    <p>Test: p 2</p> 
    <h1>Test 2</h1> 
    <p>Test2: p 1</p> 
    <p>Test2: p 2</p> 
    <p>Test2: p 3</p> 
</html> 

這裏的XSLT:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
     <content> 
      <xsl:apply-templates/> 
     </content> 
    </xsl:template> 

    <xsl:template match="h1"> 
     <section> 
      <sectionHeading> 
       <xsl:apply-templates/> 
      </sectionHeading> 
      <sectionContent> 
       <xsl:for-each select="following-sibling::p"> 
        <paragraph> 
         <xsl:value-of select="."/> 
        </paragraph> 
       </xsl:for-each> 
      </sectionContent> 
     </section> 
    </xsl:template> 

    <xsl:template match="p"/> 
</xsl:stylesheet> 

這裏的當前結果:

<?xml version="1.0" encoding="UTF-8"?> 
<content> 
    <section> 
     <sectionHeading>Test</sectionHeading> 
     <sectionContent> 
      <paragraph>Test: p 1</paragraph> 
      <paragraph>Test: p 2</paragraph> 
      <paragraph>Test: p 3</paragraph> 
      <paragraph>Test2: p 1</paragraph> 
      <paragraph>Test2: p 2</paragraph> 
     </sectionContent> 
    </section> 
    <section> 
     <sectionHeading>Test 2</sectionHeading> 
     <sectionContent> 
      <paragraph>Test2: p 1</paragraph> 
      <paragraph>Test2: p 2</paragraph> 
     </sectionContent> 
    </section> 
</content> 

這裏是預期的結果:

<?xml version="1.0" encoding="UTF-8"?> 
<content> 
<section> 
    <sectionHeading>Test</sectionHeading> 
    <sectionContent> 
     <paragraph>Test: p 1</paragraph> 
     <paragraph>Test: p 2</paragraph> 
     <paragraph>Test: p 3</paragraph> 
    </sectionContent> 
</section> 
<section> 
    <sectionHeading>Test 2</sectionHeading> 
    <sectionContent> 
     <paragraph>Test2: p 1</paragraph> 
     <paragraph>Test2: p 2</paragraph> 
    </sectionContent> 
</section> 
</content> 
+0

@添,雖然我們可以得到XSLT一個解決方案,我寧願建議你到XML格式更改爲

測試

測試:第1頁

測試:第2頁

試驗2

Test2的:p 1

Test2的:p 2

Test2:p 3

哪個更合理,可讀性強,易於在xslt中查詢。 – Ravisha 2010-01-30 04:05:16

回答

25

試試這個:(而不是要求所有p的,我們要求所有的P公司,其最近前面的H1是當前的)。

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="/"> 
     <content> 
      <xsl:apply-templates/> 
     </content> 
    </xsl:template> 

    <xsl:template match="h1"> 
     <xsl:variable name="header" select="."/> 
     <section> 
      <sectionHeading> 
       <xsl:apply-templates/> 
      </sectionHeading> 
      <sectionContent> 
       <xsl:for-each select="following-sibling::p[preceding-sibling::h1[1] = $header]"> 
        <paragraph> 
         <xsl:value-of select="."/> 
        </paragraph> 
       </xsl:for-each> 
      </sectionContent> 
     </section> 
    </xsl:template> 

    <xsl:template match="p"/> 
</xsl:stylesheet> 
+0

剛剛測試過,它的工作完美。非常感謝你。 – Tim 2010-01-29 22:39:04

+0

如果有效,請接受解決方案。 – 2010-01-29 22:52:16

+0

接受的答案。 – Tim 2010-01-29 23:03:04

4

接受的答案有一個不好的副作用,它是有點不對。

此外,在這篇文章中,我將解釋真正比較下列基本語句,以及爲什麼它可以失敗。


重溫/分析的情況,而在模板<xsl:template match="h1">是:

  • 當前上下文節點是匹配的<xsl:template>任何h1
  • 變量名稱header包含我當前上下文節點的副本。

基本語句這是壞/錯誤:

以下同胞:: P [前同輩:: H1 [1] = $頭]

  • 選擇我的上下文節點|的所有後續兄弟姐妹pfollowing-sibling::p
  • 濾波器這些p其中第一(最接近)前同輩命名h1「是」相同可變$header | ...[preceding-sibling::h1[1] = $header]

!!在XSLT 1.0中,一個節點與一個節點的比較將通過它的值來完成!


在示例中查看。讓我們假裝輸入XML是這樣的[<h1>包含兩次相同的值Test]:

<html> 
    <h1>Test</h1> 
    <p>Test: p 1</p> 
    <p>Test: p 2</p> 
    <h1>Test</h1> 
    <p>Test2: p 1</p> 
    <p>Test2: p 2</p> 
    <p>Test2: p 3</p> 
</html> 

一個錯!結果將被創建:

<content> 
    <section> 
    <sectionHeading>Test</sectionHeading> 
    <sectionContent> 
     <paragraph>Test: p 1</paragraph> 
     <paragraph>Test: p 2</paragraph> 
     <paragraph>Test2: p 1</paragraph> <-- should be only in 2. section 
     <paragraph>Test2: p 2</paragraph> <-- should be only in 2. section 
     <paragraph>Test2: p 3</paragraph> <-- should be only in 2. section 
    </sectionContent> 
    </section> 
    <section> 
    <sectionHeading>Test</sectionHeading> 
    <sectionContent> 
     <paragraph>Test2: p 1</paragraph> 
     <paragraph>Test2: p 2</paragraph> 
     <paragraph>Test2: p 3</paragraph> 
    </sectionContent> 
    </section> 
</content> 

正確的比較

.... 
<xsl:variable name="header" select="generate-id(.)"/> 
.... 
<xsl:for-each select="following-sibling::p[generate-id(preceding-sibling::h1[1]) = $header]"> 
.... 

使用功能generate-id()得到唯一的(至少在當前文檔中)節點的ID,現在比較節點VS節點!即使您使用<xsl:key>這種技術,您也必須使用generate-id!

+0

爲什麼不編輯接受的解決方案並添加評論? – 2018-02-21 19:07:30