2017-06-05 12 views
1

構造化されたXML文書に変換しようとしている基本的なePub出力からのXHTML文書があります。その形式は、一般的には、あまりにも夢中になると、以下のように見えるべきではありません。XSLT 1.0の構造化XMLへのXHTML

<?xml version="1.0" encoding="utf-8"?> 
<html> 
<body> 
    <h1>Topic 1</h1> 
    <p>1.0.1</p> 
    <p>1.0.2</p> 

    <h2>Subtopic 1.1</h2> 
    <p>1.1.1</p> 
    <p>1.1.2</p> 

    <h2>Subtopic 1.2</h2> 
    <p>1.2.1</p> 
    <p>1.2.2</p> 

    <h1>Topic 2</h1> 
    <p>2.0.1</p> 
    <p>2.0.2</p> 

    <h2>Subtopic 2.1</h2> 
    <p>2.1.1</p> 
    <p>2.1.2</p> 

    <h2>Subtopic 2.2</h2> 
    <p>2.2.1</p> 
    <p>2.2.2</p> 
</body> 
</html> 

理想的には、私は、H1、H2に基づいて、いくつかの構造化されたコードにこれを変換したいのですが...タグ。最初のh1の後のもの、しかし2番目のものの前のものは、それ自身のコンテナの中に含まれなければならず、2番目のh1のものは、それ自身の内部の文書の最後まで含まれていなければなりません。同様に、h2の間のものもコンテナに入れ、それを入れ子にする必要があります。出力は次のようなものでなければなりません:

は例のみのpタグで構成されていても
<Root> 
    <Topic> 
     <Title>Topic 1</Title> 
     <Paragraph>1.0.1</Paragraph> 
     <Paragraph>1.0.2</Paragraph> 
     <Topic> 
     <Title>Subtopic 1.1</Title> 
     <Paragraph>1.1.1</Paragraph> 
     <Paragraph>1.1.2</Paragraph> 
     </Topic> 
     <Topic> 
     <Title>Subtopic 1.2</Title> 
     <Paragraph>1.2.1</Paragraph> 
     <Paragraph>1.2.2</Paragraph> 
     </Topic> 
    </Topic> 
    <Topic> 
     <Title>Topic 2</Title> 
     <Paragraph>2.0.1</Paragraph> 
     <Paragraph>2.0.2</Paragraph> 
     <Topic> 
     <Title>Subtopic 2.1</Title> 
     <Paragraph>2.1.1</Paragraph> 
     <Paragraph>2.1.2</Paragraph> 
     </Topic> 
     <Topic> 
     <Title>Subtopic 2.2</Title> 
     <Paragraph>2.2.1</Paragraph> 
     <Paragraph>2.2.2</Paragraph> 
     </Topic> 
    </Topic> 
</Root> 

、それはまたのdivの、および他の元素を含むことができるので、それだけで一つのノードであることにカウントされません。ヘッダータグの間に何がないか気にしないで十分な汎用性が必要です。

私はMuenchianグループに精通していますが、これは私にとっては少し複雑な状況です。私はこのようなキーを使用して試してみた:

<xsl:key name="kHeaders1" match="*[not(self::h1)]" use="generate-id(preceding-sibling::h1[1])"/> 

<xsl:template match="h1"> 
    <Topic> 
    <Title><xsl:apply-templates /></Title> 
    <xsl:apply-templates select="key('kHeaders1', generate-id())" /> 
    </Topic> 
</xsl:template> 

<xsl:template match="html"> 
    <Root> 
    <xsl:apply-templates select="body/h1" /> 
    </Root> 
</xsl:template> 

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

これは最初のレベルのために十分に機能しますが、このプロセスを繰り返ししようとしているが、H2を使用して、私の心を破るようです。 h2レベルでは、どのノードのキーも最初のh1またはh2の兄弟でなければなりません。それは、それが以前のh *がどんなものであってもh *要素がグループ化されていない(つまり、それらが再帰しないように) )。しかし、それは前のH1のためのグループ化に存在する必要がリストからH2要素を、抜けて

<xsl:key name="kHeaders" match="*[not(self::h1 or self::h2)]" use="generate-id(preceding-sibling::*[self::h1 or self::h2][1])"/> 

:私のようなものを想像するでしょう。また、h1/h2要素を含むように一致の制限を緩和し(h1テンプレートもh2と一致させる)、h2のh1の再リストアを取得します(やや期待されます)。

理想的な解決策は、h3、h4などの作業に多くの労力を費やすことなく拡張することができるソリューションです。ただし、ジェネリックh *要素を処理するためのスクリプト要素を含める必要はありません。追加のレイヤーを追加する簡単な手順で十分です。

誰かアドバイスがありますか?

答えて

1

this answerからコピーされた基本的なコードのほとんどは)複数のヘッダが関与しているときに動作しますが:

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

    <xsl:key name="next-headings" match="h6" 
      use="generate-id(preceding-sibling::*[self::h1 or self::h2 or 
               self::h3 or self::h4 or 
               self::h5][1])" /> 

    <xsl:key name="next-headings" match="h5" 
      use="generate-id(preceding-sibling::*[self::h1 or self::h2 or 
               self::h3 or self::h4][1])" /> 
    <xsl:key name="next-headings" match="h4" 
      use="generate-id(preceding-sibling::*[self::h1 or self::h2 or 
               self::h3][1])" /> 
    <xsl:key name="next-headings" match="h3" 
      use="generate-id(preceding-sibling::*[self::h1 or self::h2][1])" /> 

    <xsl:key name="next-headings" match="h2" 
      use="generate-id(preceding-sibling::h1[1])" /> 

    <xsl:key name="immediate-nodes" 
      match="node()[not(self::h1 | self::h2 | self::h3 | self::h4 | 
          self::h5 | self::h6)]" 
      use="generate-id(preceding-sibling::*[self::h1 or self::h2 or 
               self::h3 or self::h4 or 
               self::h5 or self::h6][1])" /> 

    <xsl:template match="/"> 
     <Root> 
      <xsl:apply-templates select="html/body/h1"/> 
     </Root> 
    </xsl:template> 

    <xsl:template match="p"> 
     <Paragraph> 
      <xsl:value-of select="."/> 
     </Paragraph> 
    </xsl:template> 

    <xsl:template match="h1 | h2 | h3 | h4 | h5 | h6"> 
     <Topic> 
      <Title> 
       <xsl:value-of select="."/> 
      </Title> 
      <xsl:apply-templates select="key('immediate-nodes', generate-id())"/> 
      <xsl:apply-templates select="key('next-headings', generate-id())"/> 
     </Topic> 
    </xsl:template> 

</xsl:stylesheet> 
+0

パーフェクト!私が記事を検索しているときに私はそれを見つけていなかったし、それは私が必要とするものの大部分を持っていたようだ。それを適用し、私の正気を保存していただきありがとうございます。私はキーに「追加」することもできないと考えました。私はそれらを一度しか定義しませんでした。だから、私も何かを学びました! – Greg

+0

あなたは大歓迎です! :) –

1

これは、トリックを行います:スタイルシートの下

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

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

    <xsl:template match="*[starts-with(local-name(), 'h')]"> 
    <xsl:variable name="lvl" select="number(substring-after(local-name(), 'h'))"/> 
    <Topic> 
     <Title> 
     <xsl:value-of select="text()"/> 
     </Title> 
     <xsl:apply-templates select="//following-sibling::*[not(starts-with(local-name(), 'h')) 
          and preceding-sibling::*[starts-with(local-name(), 'h')][1] = current()]"/> 
     <xsl:apply-templates select="//following-sibling::*[local-name() = concat('h', $lvl + 1) 
          and preceding-sibling::*[local-name() = concat('h', $lvl)][1] = current()]"/> 
    </Topic> 
    </xsl:template> 

    <xsl:template match="*"> 
    <Paragraph> 
     <xsl:value-of select="text()"/> 
    </Paragraph> 
    </xsl:template> 
</xsl:stylesheet> 
+0

また、私はこれをテストし、それトリックだが、鍵がないようだ。もう少し凝縮されています。それを簡単に行うことができるということを知るためには健全性の節約ではありませんが、それでも完全に有効な答えです! – Greg

+0

@Greg、cool thanks –

関連する問題