2

次の構造が与えられます:

<TITEL1>...</TITEL1>  
<p>..</p>
<TITEL2>...</TITEL2>  
<TITEL3>...</TITEL3>
<TITEL3>...</TITEL3>  
<P>...<P>  

これに到達する方法はありますか:

<TITEL1>
    <TITEL>...</TITEL>  
    <p>...</p>
    <TITEL2>
        <TITEL>...</TITEL>  
        <TITEL3>
            <TITEL>...</TITEL>
            <P>...</P>
        </TITEL3>
        <TITEL3>
            <TITEL>...</TITEL>
            <P>...</P>
        </TITEL3>
    </TITEL2>
</TITEL1>

つまり、高レベルのタイトルを低レベルのタイトルとそれに続くすべてのコンテンツに近づけて、ネストされた構造を作成する方法はありますか。各TITEL1、2、および3タグのコンテンツは、新しい要素に入れる必要があり<TITEL>ます

4

3 に答える 3

2

あなたがやりたいことをするための特に適格な方法はありません。それは(おそらく)可能ですが、現在のノードに一致する軸上のフィルターを備えたfollowing-sibling軸を使用した、かなり醜い(そして遅い)XPathクエリが含まれます。preceding-sibling

可能であれば、XSLTの外部(C#、Javaなど)で階層を作成することをお勧めします

あなたが恐ろしい道を進むことを選択した場合、あなたはこのようなことをしようとしているでしょう(テストされていない):

<xsl:template match="TITEL1">
  <TITEL1>
    <xsl:apply-templates 
      select="following-sibling::(p|TITEL2)[(preceding-sibling::TITEL1)[1]=.]" />
  </TITEL1>
</xsl:template>

<xsl:template match="TITEL2">
  <TITEL1>
    <xsl:apply-templates 
      select="following-sibling::(p|TITEL3)[(preceding-sibling::TITEL2)[1]=.]" />
  </TITEL1>
</xsl:template>

...

これはほんの一例であり、私はすでに試合の問題を見ることができます。実際に可能であれば、最終的なXPathクエリを考え出すことは非常に複雑です。

于 2010-01-21T10:30:28.280 に答える
2

XSLT 2.0(Saxon 9またはAltovaXMLツールによって実装される)では、xsl:for-each-groupgroup-starting-withおよび再帰関数を使用できます。

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:mf="http://example.com/2010/mf"
  exclude-result-prefixes="xsd mf">

  <xsl:output indent="yes"/>

  <xsl:function name="mf:nest" as="element()*">
    <xsl:param name="elements" as="element()*"/>
    <xsl:param name="level" as="xsd:integer"/>
    <xsl:for-each-group select="$elements" group-starting-with="*[starts-with(local-name(), concat('TITEL', $level))]">
      <xsl:choose>
        <xsl:when test="self::*[starts-with(local-name(), concat('TITEL', $level))]">
          <xsl:element name="TITEL{$level}">
            <xsl:apply-templates select="."/>
            <xsl:sequence select="mf:nest(current-group() except ., $level + 1)"/>
          </xsl:element>
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-templates select="current-group()"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:for-each-group>
  </xsl:function>

  <xsl:template match="ROOT">
    <xsl:sequence select="mf:nest(*, 1)"/>
  </xsl:template>

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

  <xsl:template match="*[starts-with(local-name(), 'TITEL')]">
    <TITEL>
      <xsl:apply-templates select="@* | node()"/>
    </TITEL>
  </xsl:template>

</xsl:stylesheet>

そのスタイルシートで入力

<ROOT>
<TITEL1>Titel 1, 1</TITEL1>  
<p>..</p>
<TITEL2>Titel 2, 1</TITEL2>  
<TITEL3>Titel 3, 1</TITEL3>
<TITEL3>Titel 3, 2</TITEL3>  
<P>...</P>
</ROOT>

出力に変換されます

<TITEL1>
   <TITEL>Titel 1, 1</TITEL>
   <p>..</p>
   <TITEL2>
      <TITEL>Titel 2, 1</TITEL>
      <TITEL3>
         <TITEL>Titel 3, 1</TITEL>
      </TITEL3>
      <TITEL3>
         <TITEL>Titel 3, 2</TITEL>
         <P>...</P>
      </TITEL3>
   </TITEL2>
</TITEL1>
于 2010-01-21T13:09:08.593 に答える
1

XSLT 2.0を使用できない場合は、以前に投稿したXSLT2.0スタイルシートと同じ結果を生成するXSLT1.0スタイルシートを次に示します。

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

  <xsl:output indent="yes"/>

  <xsl:template match="ROOT">
    <xsl:apply-templates select="*[1]" mode="nest">
      <xsl:with-param name="level" select="1"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="*[starts-with(local-name(), 'TITEL')]" mode="nest">
    <xsl:param name="level"/>
    <xsl:choose>
      <xsl:when test="$level = substring-after(local-name(), 'TITEL')">
        <xsl:element name="TITEL{$level}">
          <xsl:apply-templates select="."/>
          <xsl:apply-templates select="following-sibling::*[1][not(starts-with(local-name(), concat('TITEL', $level)))]" mode="nest">
            <xsl:with-param name="level" select="$level"/>
          </xsl:apply-templates>
        </xsl:element>
        <xsl:apply-templates select="following-sibling::*[starts-with(local-name(), concat('TITEL', $level))][1]" mode="nest">
          <xsl:with-param name="level" select="$level"/>
        </xsl:apply-templates>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates select="." mode="nest">
          <xsl:with-param name="level" select="$level + 1"/>
        </xsl:apply-templates>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

  <xsl:template match="*[not(starts-with(local-name(), 'TITEL'))]" mode="nest">
    <xsl:param name="level"/>
    <xsl:apply-templates select="."/>
    <xsl:apply-templates select="following-sibling::*[1][not(starts-with(local-name(), concat('TITEL', $level)))]" mode="nest">
      <xsl:with-param name="level" select="$level"/>
    </xsl:apply-templates>
  </xsl:template>

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

  <xsl:template match="*[starts-with(local-name(), 'TITEL')]">
    <TITEL>
      <xsl:apply-templates select="@* | node()"/>
    </TITEL>
  </xsl:template>

</xsl:stylesheet>
于 2010-01-21T17:17:10.257 に答える