2011-12-12 65 views
0

我有以下XML。如何通過XSLT移動元素

<body> 
    <p type="Heading 1">My Heading</p> 
    <p>This is paragraph Text... This is paragraph text... <p type="Key Words">This is a keyword A</p></p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text... <p type="Key Words">This is a keyword B</p></p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p type="Heading 1">My Next Heading</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... <p type="Key Words">This is a keyword C</p>This is paragraph text...</p> 
    <p type="Heading 2">My Next Heading</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... <p type="Key Words">This is a keyword D</p> This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
</body> 
只是下一標題之前,如下圖所示

我想移動所有的「關鍵詞」的:

<body> 
    <p type="Heading 1">My Heading</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p type="Key Words">This is a keyword A</p> 
    <p type="Key Words">This is a keyword B</p> 
    <p type="Heading 1">My Next Heading</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p type="Key Words">This is a keyword C</p> 
    <p type="Heading 2">My Next Heading</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p>This is paragraph Text... This is paragraph text...</p> 
    <p type="Key Words">This is a keyword D</p> 
</body> 

我有工作的代碼,但它有嚴重的性能問題,因爲我我正在對數十萬字的文檔進行這種轉換。以下是我目前的代碼。

<!-- Place all keywords in section right before the next heading title. --> 
<xsl:template match="p[contains(@type,'Heading')]"> 

    <xsl:variable name="headingCount" > 
    <xsl:value-of select="count(preceding::p[contains(@type,'Heading')])"/> 
    </xsl:variable> 

    <xsl:variable name="precedingKeyWordCount"> 
    <xsl:value-of select="count(preceding::p[contains(@type,'Key Words') and count(preceding::p[contains(@type,'Heading')]) = $headingCount])"/> 
    </xsl:variable> 


    <xsl:if test="$precedingKeyWordCount > 0" > 
    <p type="Key Words"> 
     <xsl:apply-templates select="preceding::p[contains(@type,'Key Words') and count(preceding::p[contains(@type,'Heading')]) = $headingCount]" /> 
    </p> 
    </xsl:if> 


    <!-- place original heading --> 
    <xsl:copy> 
    <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 


</xsl:template> 

有沒有人知道更有效的方法來實現這一目標?

謝謝。

回答

1

稍微簡單的例子(即假設Key Words段落可以被複制到全輸出):

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes"/> 
    <xsl:key name="byHeading" match="p[@type='Key Words']" 
      use="generate-id(following::p[starts-with(@type, 'Heading')][1])"/> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="body"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
      <xsl:copy-of select="key('byHeading', '')"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="p[starts-with(@type, 'Heading')]"> 
     <xsl:copy-of select="key('byHeading', generate-id())"/> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="p[@type='Key Words']"/> 
</xsl:stylesheet> 

與你原來的樣式表的主要問題是,它需要看每個前面的元素在文檔多每個標題的時間。軸上的precedingfollowing通常會導致大型文檔的性能問題。

我們可以通過將其與key預先分組來避免此性能問題。

1

下面是一個使用密鑰的例子:

<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

    <xsl:strip-space elements="*"/> 
    <xsl:output indent="yes"/> 

    <xsl:key name="k1" 
    match="p/p[@type = 'Key Words']" 
    use="generate-id(parent::p/following-sibling::p[starts-with(@type, 'Heading')][1])"/> 

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

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

    <xsl:template match="body/p[starts-with(@type, 'Heading')]"> 
    <xsl:apply-templates select="key('k1', generate-id())"/> 
    <xsl:call-template name="identity"/> 
    </xsl:template> 

    <xsl:template match="body/p[not(@type) or not(starts-with(@type, 'Heading'))]"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()[not(self::p[@type = 'Key Words'])]"/> 
    </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

這應該有更好的表現。

+0

謝謝,但我需要一個不依賴於結構體/ p/p的解決方案。 – joe

+0

好吧,我想我可以馴服它。謝謝您的幫助! – joe