2010-04-08 74 views
1

我遇到了一些XML轉換問題,需要一些幫助。XML轉換元素出現在文檔中的錯誤位置

樣式表應該通過所有後綴元件迭代和放置內容,而不用它的第一祖先報價區元素內毗鄰最後一個文本節點後綴標記(見所需輸出中)。它僅在單個後綴存在時起作用,但當2出現時不起作用,當出現2時,它將兩個後綴都放在第一個引用塊的最後一個文本節點中。

任何想法?我試圖在各個地方限制選擇祖先:: quote-block [1],但這並沒有達到預期的效果。

源XML

<paragraph> 
    <para> 
     <quote-block> 
      <list prefix-rules="specified"> 
       <item prefix="「B42"> 
        <para id="0a84d149-91b7-4012-ac6d-9f4eb8ed6c37">In June 2000, EME and EWS 
         reached an agreement to negotiate towards a direct contract for coal haulage 
         by rail (on a DIY basis), which would replace the previous indirect E2E 
         arrangements that EME had in place with ECSL. An internal EWS e-mail noted: <quote-block> 
          <quote-para>‘We did the deal with Edison Mission yesterday morning for 
           LBT-Fiddlers @ £[…]/tonne as agreed. This rate until 16th September 
           pending a contract.</quote-para> 
          <quote-para><emphasis strength="strong">Enron are now off our hands so 
            far as Edison are concerned. The Enron flows we have left are to 
            British Energy’s station at Eggborough; from Immingham, Redcar 
            and Hull</emphasis>. Also to Enron’s own power station at Wilton 
           – 250,000 tonnes/year. I think we are stuck Enron [sic] on the 
           Eggborough traffic until next April when British Energy will, 
           hopefully take over their own coal procurement. <emphasis 
            strength="strong">But we have got them out of Fiddlers Ferry and 
            Ferrybridge – a big step forward</emphasis>.’</quote-para> 
          <suffix>(Emphasis added.)</suffix> 
         </quote-block> 
        </para> 
       </item> 
       <item prefix="B43"> 
        <para id="d64a5a72-0a02-476f-9a7b-7c07bbc93a8a">This e-mail is evidence of both 
         EWS’s intent and, indeed, its success in stopping ECSL from carrying out 
         indirect supplies to EME, one of the new generating companies.」</para> 
       </item> 
      </list> 
      <suffix>(emphasis in original)</suffix> 
     </quote-block> 
    </para> 
</paragraph> 

樣式表

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://xml.sm.com/schema/cases/report" 
    xmlns:sm="http://xml.sm.com/functions" xmlns:saxon="http://saxon.sf.net/" 
    xpath-default-namespace="http://sm.com/schema/cases/report" 
    exclude-result-prefixes="xs sm" version="2.0"> 

    <xsl:output method="xml" indent="no"/> 

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

    <xsl:template match="*"> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
      <xsl:apply-templates/> 
     </xsl:copy> 
    </xsl:template> 

    <!-- Match quote-blocks with open or close attributes. --> 
    <xsl:template match="*[*:quote-block and descendant::*:suffix]"> 
     <xsl:call-template name="process-quote-block"/> 
    </xsl:template> 

    <!-- Match inline quote with open or close attributes --> 
    <xsl:template match="*[*:quote and descendant::*:suffix]"> 
     <xsl:call-template name="process-quote-block"/> 
    </xsl:template> 

    <!-- Process the quote block --> 
    <xsl:template name="process-quote-block"> 
     <xsl:variable name="quoteBlockCopy"> 
      <xsl:copy-of select="."/> 
     </xsl:variable> 

     <xsl:apply-templates select="$quoteBlockCopy" mode="append-suffix"> 
      <xsl:with-param name="suffix" select="sm:get-suffix-note(.)"/> 
      <xsl:with-param name="end-node" select="sm:get-last-text-node($quoteBlockCopy)"/> 
     </xsl:apply-templates> 
    </xsl:template> 

    <!-- Match quote-blocks with open or close attributes. --> 
    <xsl:template match="*[*:quote-block and descendant::*:suffix][ancestor::*:quote-block[1]]" mode="create-copy"> 
     <xsl:call-template name="process-quote-block"/> 
    </xsl:template> 

    <!-- Match inline quote with open or close attributes --> 
    <xsl:template match="*[*:quote and descendant::*:suffix]" mode="create-copy"> 
     <xsl:call-template name="process-quote-block"/> 
    </xsl:template> 

    <!-- This will match all elements. Just copy and pass through the parameters. --> 
    <xsl:template match="*" mode="append-suffix"> 
     <xsl:param name="suffix"/> 
     <xsl:param name="end-node"/> 
     <xsl:copy> 
      <xsl:copy-of select="@*"/> 
      <xsl:apply-templates mode="append-suffix"> 
       <xsl:with-param name="suffix" select="$suffix"/> 
       <xsl:with-param name="end-node" select="$end-node"/> 
      </xsl:apply-templates> 
     </xsl:copy> 
    </xsl:template> 

    <!-- Apply the text node to the content. If the node is equal to the last node then append the descendants of suffix --> 
    <xsl:template match="text()[normalize-space() != '']" mode="append-suffix"> 
     <xsl:param name="suffix"/> 
     <xsl:param name="end-node"/> 
     <xsl:choose> 
      <xsl:when test="count(. | $end-node) = 1"> 
       <xsl:value-of select="."/> 
       <xsl:apply-templates select="$suffix"/> 
      </xsl:when> 
      <xsl:otherwise> 
       <!-- Or maybe neither. --> 
       <xsl:value-of select="."/> 
      </xsl:otherwise> 
     </xsl:choose> 
    </xsl:template> 

    <!-- Dont copy suffix as --> 
    <xsl:template match="*:suffix" mode="append-suffix"/> 

    <xsl:function name="sm:get-suffix-note"> 
     <xsl:param name="node"/> 
     <xsl:sequence select="$node/descendant::*:suffix/node()"/> 
    </xsl:function> 

    <xsl:function name="sm:get-last-text-node"> 
     <!-- Finds last non-empty text() node, ignoring <suffix> elements that are a child of this specific quote-block. --> 
     <xsl:param name="node"/> 

     <xsl:sequence 
      select="reverse($node//text()[not(ancestor::*:suffix) and normalize-space() != ''])[1]"/> 
    </xsl:function> 

</xsl:stylesheet> 

電流輸出XML

<paragraph> 
    <para> 
     <quote-block> 
      <list prefix-rules="specified"> 
       <item prefix="「B42"> 
        <para id="0a84d149-91b7-4012-ac6d-9f4eb8ed6c37">In June 2000, EME and EWS 
         reached an agreement to negotiate towards a direct contract for coal haulage 
         by rail (on a DIY basis), which would replace the previous indirect E2E 
         arrangements that EME had in place with ECSL. An internal EWS e-mail noted: <quote-block> 
          <quote-para>‘We did the deal with Edison Mission yesterday morning for 
           LBT-Fiddlers @ £[…]/tonne as agreed. This rate until 16th September 
           pending a contract.</quote-para> 
          <quote-para><emphasis strength="strong">Enron are now off our hands so 
            far as Edison are concerned. The Enron flows we have left are to 
            British Energy’s station at Eggborough; from Immingham, Redcar 
            and Hull</emphasis>. Also to Enron’s own power station at Wilton 
           – 250,000 tonnes/year. I think we are stuck Enron [sic] on the 
           Eggborough traffic until next April when British Energy will, 
           hopefully take over their own coal procurement. <emphasis 
            strength="strong">But we have got them out of Fiddlers Ferry and 
            Ferrybridge – a big step forward</emphasis>.’</quote-para> 
         </quote-block> 
        </para> 
       </item> 
       <item prefix="B43"> 
        <para id="d64a5a72-0a02-476f-9a7b-7c07bbc93a8a">This e-mail is evidence of both 
         EWS’s intent and, indeed, its success in stopping ECSL from carrying out 
         indirect supplies to EME, one of the new generating companies.」(Emphasis 
         added.)(emphasis in original)</para> 
       </item> 
      </list> 

     </quote-block> 
    </para> 
</paragraph> 

希望的輸出繼電器

<paragraph> 
    <para> 
     <quote-block> 
      <list prefix-rules="specified"> 
       <item prefix="「B42"> 
        <para id="0a84d149-91b7-4012-ac6d-9f4eb8ed6c37">In June 2000, EME and EWS 
         reached an agreement to negotiate towards a direct contract for coal haulage 
         by rail (on a DIY basis), which would replace the previous indirect E2E 
         arrangements that EME had in place with ECSL. An internal EWS e-mail noted: <quote-block> 
          <quote-para>‘We did the deal with Edison Mission yesterday morning for 
           LBT-Fiddlers @ £[…]/tonne as agreed. This rate until 16th September 
           pending a contract.</quote-para> 
          <quote-para><emphasis strength="strong">Enron are now off our hands so 
            far as Edison are concerned. The Enron flows we have left are to 
            British Energy’s station at Eggborough; from Immingham, Redcar 
            and Hull</emphasis>. Also to Enron’s own power station at Wilton 
           – 250,000 tonnes/year. I think we are stuck Enron [sic] on the 
           Eggborough traffic until next April when British Energy will, 
           hopefully take over their own coal procurement. <emphasis 
            strength="strong">But we have got them out of Fiddlers Ferry and 
            Ferrybridge – a big step forward</emphasis>.’(Emphasis 
           added.)</quote-para> 
         </quote-block> 
        </para> 
       </item> 
       <item prefix="B43"> 
        <para id="d64a5a72-0a02-476f-9a7b-7c07bbc93a8a">This e-mail is evidence of both 
         EWS’s intent and, indeed, its success in stopping ECSL from carrying out 
         indirect supplies to EME, one of the new generating companies.」(emphasis in original)</para> 
       </item> 
      </list> 

     </quote-block> 
    </para> 
</paragraph> 

回答

1

男人,你已經在這裏挖了一個洞。 ;-)這裏是我想出了:

<xsl:stylesheet 
    version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
> 
    <xsl:output method="xml" encoding="utf-8" indent="no"/> 

    <!-- key to identify all non-empty, non-suffix text node descendants of 
     a quote-block. We'll use that to pull out the "last one" later-on --> 
    <xsl:key 
    name ="kQbText" 
    match="quote-block//text()[not(normalize-space() = '' or parent::suffix)]" 
    use ="generate-id(ancestor::quote-block[1])" 
    /> 

    <!-- identity template to copy everything that is not otherwise handled --> 
    <xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:copy> 
    </xsl:template> 

    <!-- special handling for text nodes that are descendants of quote-blocks --> 
    <xsl:template match="quote-block//text()[not(normalize-space() = '' or parent::suffix)]"> 
    <xsl:variable name="qb" select="ancestor::quote-block[1]" /> 

    <!-- the text node gets copied regardless --> 
    <xsl:copy-of select="." /> 

    <!-- if it is the last non-empty text node, append all suffices --> 
    <xsl:if test=" 
     generate-id() 
     = 
     generate-id(key('kQbText', generate-id($qb))[last()]) 
    "> 
     <xsl:for-each select="$qb/suffix"> 
     <xsl:value-of select="concat(' ', .)" /> 
     </xsl:for-each> 
    </xsl:if> 
    </xsl:template> 

    <!-- empty text nodes will be removed (all others are copied) --> 
    <xsl:template match="text()[normalize-space() = '']" /> 

    <!-- suffix nodes will be deleted--> 
    <xsl:template match="suffix" /> 

</xsl:stylesheet> 

在上面的結果(整潔增加縮進和換行符,使其可讀):

<paragraph> 
    <para> 
    <quote-block> 
     <list prefix-rules="specified"> 
     <item prefix="「B42"> 
      <para id="0a84d149-91b7-4012-ac6d-9f4eb8ed6c37">In June 
      2000, EME and EWS reached an agreement to negotiate 
      towards a direct contract for coal haulage by rail (on a 
      DIY basis), which would replace the previous indirect E2E 
      arrangements that EME had in place with ECSL. An internal 
      EWS e-mail noted: 
      <quote-block> 
      <quote-para>‘We did the deal with Edison Mission 
      yesterday morning for LBT-Fiddlers @ £[…]/tonne as 
      agreed. This rate until 16th September pending a 
      contract.</quote-para> 
      <quote-para> 
      <emphasis strength="strong">Enron are now off our hands 
      so far as Edison are concerned. The Enron flows we have 
      left are to British Energy’s station at Eggborough; 
      from Immingham, Redcar and Hull</emphasis>. Also to 
      Enron’s own power station at Wilton – 250,000 
      tonnes/year. I think we are stuck Enron [sic] on the 
      Eggborough traffic until next April when British Energy 
      will, hopefully take over their own coal procurement. 
      <emphasis strength="strong">But we have got them out of 
      Fiddlers Ferry and Ferrybridge – a big step 
      forward</emphasis>.’ (Emphasis added.)</quote-para> 
      </quote-block></para> 
     </item> 
     <item prefix="B43"> 
      <para id="d64a5a72-0a02-476f-9a7b-7c07bbc93a8a">This 
      e-mail is evidence of both EWS’s intent and, indeed, its 
      success in stopping ECSL from carrying out indirect 
      supplies to EME, one of the new generating companies.」 
      (emphasis in original)</para> 
     </item> 
     </list> 
    </quote-block> 
    </para> 
</paragraph> 

的XSLT代碼這裏是XSLT 1.0,但您可以在2.0處理器中不變地運行它。

+0

嗨Tomalak,感謝幫助,肯定幫助我擺脫困境0) – Mike 2010-04-09 07:26:30

+0

@Mike:很高興提供幫助。不要猶豫,問是否需要更徹底的解釋。 – Tomalak 2010-04-09 08:42:55

1

下面是一個簡單的變換,它只是不會忽略這個問題。正如其他人已經注意到的那樣,這個問題是非常混亂的,並且不允許一個單一的,明確的解釋。

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

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

<xsl:key name="kLastNonSufText" 
    match="*[not(self::suffix)]/text()" 
    use="generate-id(ancestor::quote-block[1])"/> 

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

<xsl:template match="text()[ancestor::quote-block]"> 
    <xsl:copy-of select="."/> 

    <xsl:variable name="vQBImmed" select="ancestor::quote-block[1]"/> 

    <xsl:variable name="vLastText" select= 
    "key('kLastNonSufText', generate-id($vQBImmed)) 
     [last()]"/> 

    <xsl:if test="count(.|$vLastText) = 1"> 
     <xsl:copy-of select="($vQBImmed//suffix)[last()]/text()"/> 
    </xsl:if> 
</xsl:template> 

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

當這個變換所提供的(非常不可讀和格式不正確)源XML文檔應用:

<paragraph> 
<para> 
    <quote-block> 
    <list prefix-rules="specified"> 
     <item prefix="「B42"> 
      <para id="0a84d149-91b7-4012-ac6d-9f4eb8ed6c37">In June 2000, EME and EWS 
       reached an agreement to negotiate towards a direct contract for coal haulage 
       by rail (on a DIY basis), which would replace the previous indirect E2E 
       arrangements that EME had in place with ECSL. An internal EWS e-mail noted: 
       <quote-block> 
        <quote-para>‘We did the deal with Edison Mission yesterday morning for 
         LBT-Fiddlers @ £[…]/tonne as agreed. This rate until 16th September 
         pending a contract.</quote-para> 
        <quote-para> 
         <emphasis strength="strong">Enron are now off our hands so 
          far as Edison are concerned. The Enron flows we have left are to 
          British Energy’s station at Eggborough; from Immingham, Redcar 
          and Hull</emphasis>. Also to Enron’s own power station at Wilton 
         – 250,000 tonnes/year. I think we are stuck Enron [sic] on the 
         Eggborough traffic until next April when British Energy will, 
         hopefully take over their own coal procurement. 
         <emphasis 
          strength="strong">But we have got them out of Fiddlers Ferry and 
          Ferrybridge – a big step forward</emphasis>.’ 
        </quote-para> 
        <suffix>(Emphasis added.)</suffix> 
       </quote-block> 
      </para> 
     </item> 
     <item prefix="B43"> 
      <para id="d64a5a72-0a02-476f-9a7b-7c07bbc93a8a">This e-mail is evidence of both 
       EWS’s intent and, indeed, its success in stopping ECSL from carrying out 
       indirect supplies to EME, one of the new generating companies.」</para> 
     </item> 
    </list> 
    <suffix>(emphasis in original)</suffix> 
    </quote-block> 
</para> 
</paragraph> 

的輸出具有附加到期望的文本節點所需後綴:

<?xml version="1.0" encoding="UTF-16"?><paragraph><para><quote-block><list prefix-rules="specified"><item prefix="「B42"><para id="0a84d149-91b7-4012-ac6d-9f4eb8ed6c37">In June 2000, EME and EWS 
       reached an agreement to negotiate towards a direct contract for coal haulage 
       by rail (on a DIY basis), which would replace the previous indirect E2E 
       arrangements that EME had in place with ECSL. An internal EWS e-mail noted: 
       <quote-block><quote-para>‘We did the deal with Edison Mission yesterday morning for 
         LBT-Fiddlers @ £[…]/tonne as agreed. This rate until 16th September 
         pending a contract.</quote-para><quote-para><emphasis strength="strong">Enron are now off our hands so 
          far as Edison are concerned. The Enron flows we have left are to 
          British Energy’s station at Eggborough; from Immingham, Redcar 
          and Hull</emphasis>. Also to Enron’s own power station at Wilton 
         – 250,000 tonnes/year. I think we are stuck Enron [sic] on the 
         Eggborough traffic until next April when British Energy will, 
         hopefully take over their own coal procurement. 
         <emphasis strength="strong">But we have got them out of Fiddlers Ferry and 
          Ferrybridge – a big step forward</emphasis>.’ 
        (Emphasis added.)</quote-para></quote-block></para></item><item prefix="B43"><para id="d64a5a72-0a02-476f-9a7b-7c07bbc93a8a">This e-mail is evidence of both 
       EWS’s intent and, indeed, its success in stopping ECSL from carrying out 
       indirect supplies to EME, one of the new generating companies.」(emphasis in original)</para></item></list></quote-block></para></paragraph> 
+0

嗨Dimitre,感謝您的幫助。在XML上指出了一點。 – Mike 2010-04-09 07:25:41

相關問題