2

私はこれに対する答えを高くも低くも見て、何百もの順列を試しましたが、何もうまくいきませんでした。

最初のノードを除いて、単純なXMLドキュメントのすべてのノードを処理しようとしてい<title>ます。基本的に、私は正確なINVERSEを達成するxslt命令を見つけようとしています。

<xsl:apply-templates select="/topic/title"/>

これが私のソースXMLです:

<topic>
    <title>Name of the Document</title>
    <p>Document body</p>
    <topic>
        <title>First Document Subtopic</title>
        <p>Body text for first document subtopic</p>
    </topic>
    <p>Body text continued for document</p>
    <topic>
        <title>Second Document Subtopic</title>
        <p>Body text for document subtopic</p>
        <topic>
            <title>First Document Sub-subtopic</title>
            <p>Body text for first document sub-subtopic</p>
        </topic>
    </topic>
    <p>Body text continued a second time for document</p>
</topic>

これが私のXSLTです(apply-templatesの呼び出しで最初に機能すると思っていたものを使用):

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

    <xsl:template match="/">
        <BOX>
            <TEXTFLOW>
                <xsl:apply-templates select="*[not(/topic/title)]"/>
            </TEXTFLOW>
        </BOX>
    </xsl:template>

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

    <xsl:template match="title">
        <PARA STYLE="Title"/>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="p">
        <PARA STYLE="BodyText"/>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="text()">
        <FORMAT>
            <xsl:value-of select="."/>
        </FORMAT>
    </xsl:template>
</xsl:stylesheet>

そして、これが私が見たいものです(最初の問題がないことに注意してください<title>):

<BOX>
    <TEXTFLOW>
        <PARA STYLE="BodyText"/>
        <FORMAT>Document body</FORMAT>
        <PARA STYLE="Title"/>
        <FORMAT>First Document Subtopic</FORMAT>
        <PARA STYLE="BodyText"/>
        <FORMAT>Body text for first document subtopic</FORMAT>
        <PARA STYLE="BodyText"/>
        <FORMAT>Body text continued for document</FORMAT>
        <PARA STYLE="Title"/>
        <FORMAT>Second Document Subtopic</FORMAT>
        <PARA STYLE="BodyText"/>
        <FORMAT>Body text for document subtopic</FORMAT>
        <PARA STYLE="Title"/>
        <FORMAT>First Document Sub-subtopic</FORMAT>
        <PARA STYLE="BodyText"/>
        <FORMAT>Body text for first document sub-subtopic</FORMAT>
        <PARA STYLE="BodyText"/>
        <FORMAT>Body text continued a second time for document</FORMAT>
    </TEXTFLOW>
</BOX>

これを実現するためにどのselect式を使用できますか?

4

2 に答える 2

6

これと同じくらい簡単

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

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

    <xsl:template match="/topic/title"/>

    <xsl:template match="title">
        <PARA STYLE="Title"/>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="p">
        <PARA STYLE="BodyText"/>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="text()">
        <FORMAT>
            <xsl:value-of select="."/>
        </FORMAT>
    </xsl:template>
</xsl:stylesheet>

この変換が提供されたXMLドキュメントに適用される場合:

<topic>
    <title>Name of the Document</title>
    <p>Document body</p>
    <topic>
        <title>First Document Subtopic</title>
        <p>Body text for first document subtopic</p>
    </topic>
    <p>Body text continued for document</p>
    <topic>
        <title>Second Document Subtopic</title>
        <p>Body text for document subtopic</p>
        <topic>
            <title>First Document Sub-subtopic</title>
            <p>Body text for first document sub-subtopic</p>
        </topic>
    </topic>
    <p>Body text continued a second time for document</p>
</topic>

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

<BOX>
   <TEXTFLOW>
      <PARA STYLE="BodyText"/>
      <FORMAT>Document body</FORMAT>
      <PARA STYLE="Title"/>
      <FORMAT>First Document Subtopic</FORMAT>
      <PARA STYLE="BodyText"/>
      <FORMAT>Body text for first document subtopic</FORMAT>
      <PARA STYLE="BodyText"/>
      <FORMAT>Body text continued for document</FORMAT>
      <PARA STYLE="Title"/>
      <FORMAT>Second Document Subtopic</FORMAT>
      <PARA STYLE="BodyText"/>
      <FORMAT>Body text for document subtopic</FORMAT>
      <PARA STYLE="Title"/>
      <FORMAT>First Document Sub-subtopic</FORMAT>
      <PARA STYLE="BodyText"/>
      <FORMAT>Body text for first document sub-subtopic</FORMAT>
      <PARA STYLE="BodyText"/>
      <FORMAT>Body text continued a second time for document</FORMAT>
   </TEXTFLOW>
</BOX>

説明

必要な要素を処理から除外するために、それらに一致し、本体を持たないテンプレートを使用します。

    <xsl:template match="/topic/title"/>

II。アップデート

次の代替ソリューションは、「プルスタイル」の例であり、上記の「プッシュスタイル」ソリューションほど柔軟でエレガントで保守しにくいため、お勧めしません。ただし、OPは、このような劣ったソリューションが必要であると主張しています。

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

    <xsl:template match="/">
      <BOX>
       <TEXTFLOW>
        <xsl:apply-templates
        select="*/*[not(self::title)]"/>
       </TEXTFLOW>
      </BOX>
    </xsl:template>

    <xsl:template match="title">
        <PARA STYLE="Title"/>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="p">
        <PARA STYLE="BodyText"/>
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="text()">
        <FORMAT>
            <xsl:value-of select="."/>
        </FORMAT>
    </xsl:template>
</xsl:stylesheet>

この変換が提供されたXMLドキュメント(上記)に適用されると、必要な正しい結果が再び生成されます

于 2012-12-24T00:13:23.073 に答える
3

ルートテンプレートでこのXPathを使用できます。

select=".//*[generate-id() != generate-id(/topic/title)]"

テンプレートを次のように変更する必要がありますtopic

<xsl:template match="topic" />

現在の選択では、処理する必要のある直接の子のみが指定されているため、問題が発生しています。ルートノート(/)から、これは実際には最上位のtopic要素にすぎません。上記のXPathのは、レベルに関係なくすべての子孫を指定し、述語は最初の要素.//*を明示的に除外します。/topic/title

topic子はルートテンプレートのselect命令によってすでに処理されているため、要素が子を処理していないことを確認する必要があります。

于 2012-12-25T00:51:39.357 に答える