2

私はxmlのようなものを持っています

<tr>
 <td class="x">1</td>
 <td class="x">2</td>
 <td>3</td>
 <td class="x">4</td>
 <td class="x">5</td>
 <td class="x">6</td>
 <td class="x">7</td>
</tr>

結果が xsl を使用するようにしたいのは次のとおりです。

\cont{1-2}
\cont{4-7}

私はこれを行うことができますか?

4

4 に答える 4

2

この変換は短く (25 行)、効率的 (キーを使用) です。

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

 <xsl:key name="kFollowing" match="td[@class='x']"
  use="concat(generate-id(..),
              '+',generate-id(preceding-sibling::*
                                 [not(self::td and @class='x')][1])
              )"/>  

 <xsl:template match="/*">
  <xsl:variable name="vGroup" 
       select="key('kFollowing', concat(generate-id(),'+'))"/>
  <xsl:value-of select=
     "concat('\cont{{',$vGroup[1],'-',$vGroup[last()],'}}','&#xA;')"/>
  <xsl:apply-templates/>
 </xsl:template>

 <xsl:template match="*/*">
  <xsl:variable name="vGroup" select=
   "key('kFollowing', concat(generate-id(..),'+', generate-id()))"/>
  <xsl:value-of select=
     "concat('\cont{{',$vGroup[1],'-',$vGroup[last()],'}}','&#xA;')"/>
 </xsl:template>

 <xsl:template match="td[@class='x']|text()"/>
</xsl:stylesheet>

提供された XML ドキュメントに適用した場合:

<tr>
    <td class="x">1</td>
    <td class="x">2</td>
    <td>3</td>
    <td class="x">4</td>
    <td class="x">5</td>
    <td class="x">6</td>
    <td class="x">7</td>
</tr>

必要な正しい結果が生成されます。

  \cont{1-2}
  \cont{4-7}
于 2012-07-13T02:11:52.803 に答える
1

上手いやり方もあれば、苦手なやり方もある。良い方法を考える時間がないのですが、これはどう思いますか?:

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

<xsl:template match="/tr">
    <xsl:for-each select="td[@class='x']">
        <xsl:variable name="currentNum" select="number(text())"/>
        <xsl:variable name="prevNum" select="number(preceding-sibling::td[@class='x'][1]/text())"/>
        <xsl:if test="($currentNum - 1) != $prevNum and $currentNum &gt; 0 and following-sibling::td[@class='x']">
            <xsl:variable name="following" select="following-sibling::td[@class='x']"/>
            <xsl:if test="number($following[1]/text()) = ($currentNum + 1)">
            \cont{<xsl:value-of select="$currentNum"/>-<xsl:call-template name="findend">
                    <xsl:with-param name="start" select="$currentNum"/>
                <xsl:with-param name="nodes" select="$following"/>
                </xsl:call-template>}
            </xsl:if>
         </xsl:if>
    </xsl:for-each>    
</xsl:template>

<xsl:template name="findend">
    <xsl:param name="nodes"/>
    <xsl:param name="start"/>
    <xsl:variable name="current" select="number($nodes[1]/text())"/>
    <xsl:choose>
        <xsl:when test="count($nodes) &lt; 2">
            <xsl:value-of select="$current"/>
        </xsl:when>
        <xsl:when test="number($nodes[2]/text()) != ($current + 1)">
            <xsl:value-of select="$current"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:call-template name="findend">
                <xsl:with-param name="nodes" select="$nodes[position() &gt; 1]"/>
                <xsl:with-param name="start" select="$current"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

</xsl:stylesheet>

出力は

\cont{1-2}
\cont{4-7}

数字が 1 つしかない場合は継続したくないため、\cont{1-1} を取得せず、それらは連続していなければならず、class= に含まれている必要があると仮定しました。 'バツ'。

もう少し時間があれば、もっと素敵なものを思い付くことができます!

ただし、説明として、番号が前の番号 + 1 と等しくない td[@class='x'] を探します (つまり、番号がないか、連続していません)。見つかった場合は、次の番号がこの番号 + 1 であることを確認し、cont{1-1} のケースを回避してから、末尾を探して出力する再帰テンプレートを呼び出します。

于 2012-07-12T14:32:37.743 に答える
1

キーとモードを使用した XSLT 1.0 のアプローチを次に示します (ただし、これらは主に複雑なテンプレート マッチ パターンを回避するためのものです)。

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

<xsl:output method="text"/>

<xsl:key name="k1" 
  match="td[@class = 'x'][preceding-sibling::*[1][self::td[@class = 'x']]]"
  use="generate-id(
         preceding-sibling::td[
           @class = 'x' and 
           not(preceding-sibling::*[1][self::td[@class = 'x']])
         ][1]
       )"/>

<xsl:template match="tr">
  <xsl:apply-templates select="td[@class = 'x' and not(preceding-sibling::*[1][self::td[@class = 'x']])]" mode="start"/>
</xsl:template>

<xsl:template match="td[@class = 'x']" mode="start">
  <xsl:text>\cont{</xsl:text>
  <xsl:value-of select="."/>
  <xsl:text>-</xsl:text>
  <xsl:apply-templates select="key('k1', generate-id())[last()]" mode="end"/>
</xsl:template>

<xsl:template match="td[@class = 'x']" mode="end">
  <xsl:value-of select="."/>
  <xsl:text>}&#10;</xsl:text>
</xsl:template>

</xsl:stylesheet>

そのスタイルシートを適用すると

<tr>
 <td class="x">1</td>
 <td class="x">2</td>
 <td>3</td>
 <td class="x">4</td>
 <td class="x">5</td>
 <td class="x">6</td>
 <td class="x">7</td>
</tr>

出力

\cont{1-2}
\cont{4-7}
于 2012-07-12T16:12:27.510 に答える