2016-08-24 2 views
0

次のようなXSL変換のケースがあります。XSL、マーカー間の要素を一致させる

私はこれがあります(私も '=' some_xml_and_text_kを無視したい

<content> 
    <block> 
    xml_and_text_0 
    </block> 
    <block> 
    xml_and_text_1 
    </block> 
    ... 
    <block> 
    xml_and_text_n 
    </block> 
</content> 

、しかし:

<content> 
    xml_and_text_0 
    <break/> 
    xml_and_text_1 
    <break/> 
    ... 
    <break/> 
    xml_and_text_n 
</content> 

私はこれに上記のXMLを回すためにXSL 2.0を使用したいが私は[XPath : select all following siblings until another sibling]と似たアプローチを使うことができると思っていますが、もっと簡単なアプローチ(あるいはより単純なXPath式)があるかもしれません。たとえば、for-eachループ内の現在のアイテムの前後にあるすべての兄弟を照合することは可能ですか?

EDIT:そのxml_and_text_iに注意してくださいは、同様に、私は内にラップしたいXHTMLに、テキストおよびXMLのミックスですので、何かのように:

<break/> 
this is an <ref id = "123">example</ref>, which is really <citation>awesome</citation> 
<break/> 

はなる:

<block>this is an <ref id = "123">example</ref>, which is really <citation>awesome</citation></block> 

答えて

2

あなたの質問は非常に混乱しています。あなたの実際の入力にの要素のテキストのノードがbreak個のノードの間に含まれている場合は、そのようにしてください。

どうやらこの質問を約をグループ化し、それのように非常に簡単に解決することができますXSLT 2.0を使用している:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/content"> 
    <xsl:copy> 
     <xsl:for-each-group select="node()" group-starting-with="break"> 
      <block> 
       <xsl:copy-of select="current-group()[not(self::break)]" /> 
      </block> 
     </xsl:for-each-group> 
    </xsl:copy> 
</xsl:template> 

</xsl:stylesheet> 
+0

私はそうは思いません。 ごとに新しいブロックが必要です.xmlとtext_iにはxmlとtextが含まれています。コピーするのはです。より正確には、xhtmlに似たマークアップ言語の段落が含まれています。「これはです。実際は awesome "です。 – zakmck

+0

@zakmck質問を編集し、上記のスタイルシートが正しく処理できない入力例を示してください。 XSLT 1.0または2.0を使用している場合も記述します。この例では –

+0

: ' いくつかのテキスト これは本当に素晴らしい ' あなたのXSL利回りいくつかの他のテキストである例、次のとおりです。 ' いくつかのテキスト これが0であります ' \t いくつかのテキスト \t は、これは例です:本当に 他のいくつかのテキスト ' である。しかし、私は期待し 、これは本当に素晴らしいです。 \t 他のテキスト zakmck

0

おかげmichael.hor257kソリューションのための(と混乱のため申し訳ありません)。あなたのアプローチは、以下に示すXSL軸に基づいて私よりもきれいです。私のバージョンではエッジケースも考慮されていますが、あなたも同じことをするようになっていると思います。この入力を考えると

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema" 
    exclude-result-prefixes="xs" 
    version="2.0"> 

    <!-- xsl:output method="xml" indent="yes"/--> 

    <xsl:template match="/content"> 
     <content> 

      <xsl:choose> 

       <!-- First of all, distinguish the case where there is at least one separator, from the ones with no separator at all --> 

       <xsl:when test="break"> 
        <xsl:for-each select="break"> 

         <!-- What do we have before the first separator? Create a block only if non-empty stuff --> 
         <xsl:if test="position() = 1"> 
          <xsl:variable name="first_block"><xsl:copy-of select="preceding-sibling::node()" /></xsl:variable> 
          <xsl:if test = "normalize-space ($first_block) != ''" > 
           <xsl:message select="concat ('1|', $first_block, '|')" /> 
           <block id = "{@id}"><xsl:copy-of select="$first_block" /></block> 
          </xsl:if> 
         </xsl:if> 

         <!-- What do we have after the next separator and before the next (or the end)? --> 
         <xsl:variable name="block_content"> 
          <xsl:choose> 
           <xsl:when test="following-sibling::break"> 
            <!-- select all that comes after current node and precedes the next separator --> 
            <xsl:copy-of select="following-sibling::node() intersect following-sibling::break[1]/preceding-sibling::node()" /> 
           </xsl:when> 
           <xsl:otherwise> 
            <!-- One separator after another, without anything in between --> 
            <xsl:copy-of select="following-sibling::node()" /> 
           </xsl:otherwise> 
          </xsl:choose>       
         </xsl:variable> 

         <xsl:message select="concat ('|', $block_content, '|')" /> 
         <xsl:message select="concat ('_|', normalize-space ($block_content), '|_')" /> 

         <!-- Did we get something after the current separator? Create a block if yes --> 
         <xsl:if test = "normalize-space($block_content) != ''"> 
          <block id = "{@id}"><xsl:copy-of select="$block_content" /></block> 
         </xsl:if>      
        </xsl:for-each> 
       </xsl:when> 

       <!-- When some content is available without any separator, create a virtual single block to represent it --> 
       <xsl:otherwise> 
        <xsl:variable name="single_block"><xsl:copy-of select="node()" /></xsl:variable> 
        <xsl:if test = "normalize-space($single_block) != ''"> 
         <block id = "00"><xsl:copy-of select = "$single_block" /></block> 
        </xsl:if> 
       </xsl:otherwise> 
      </xsl:choose> 

     </content> 

    </xsl:template> 

</xsl:stylesheet> 

<content> 
    Some <b>text</b> 
    <break id = '1'/> 
    this is an <ref id = "123">example</ref>, which is really <citation>awesome</citation> 
    <break id = '2'/> 
    Some other text 
</content> 

をそれは、この出力を生成します:

<?xml version="1.0" encoding="UTF-8"?> 
<content> 
    <block id="1"> Some <b>text</b></block> 
    <block id="1"> this is an <ref id="123">example</ref>, which is really<citation>awesome</citation></block> 
    <block id="2"> Some other text </block> 
</content> 
関連する問題