2

これは非常に複雑な問題であり、XSLTに関する私の知識を超えています。私はまだ学習中であり、O'ReillyのXSLTの本をどれだけ読んでも、頭上にいます。

入力XMLファイルを作成した多面的な問題があり、後で要件についても説明します。

入力

<roottag>
<body>
    <header>
        <r>
            <c>
                <d>Header Tag</d><!-- This can include spaces-->
                <e>System generated trash</e>
            </c>
        </r>
        <r>
            <c>
                <d>Sub Header Tag A</d>
                <e>System generated trash</e>
            </c>
            <c>
                <d>Sub Header Value A</d>
                <e>System generated trash</e>
            </c>
        </r>
        <r>
            <c>
                <d>Sub Header Tag B</d>
                <e>System generated trash</e>
            </c>
            <c>
                <d>Sub Header Value B</d>
                <e>System generated trash</e>
            </c>
        </r>
        <r>
            <c>
                <d>Sub Header Tag C</d>
                <e>System generated trash</e>
            </c>
            <c>
                <d>Sub Header Value C</d>
                <e>System generated trash</e>
            </c>
        </r>
    </header>
    <information>
        <r>Body of document</r>
        <r>Appears here but have an XSLT that deals with this</r>
    </informtaion>
    <footer>
        <r>
            <c>
                <d>Footer Tag</d><!-- This can include spaces-->
                <e>System generated trash</e>
            </c>
        </r>
        <r>
            <c>
                <d>Sub Footer Tag A</d>
                <e>System generated trash</e>
            </c>
            <c>
                <d>Sub Footer Value A</d>
                <e>System generated trash</e>
            </c>
        </r>
        <r>
            <c>
                <d>Sub Footer Tag B</d>
                <e>System generated trash</e>
            </c>
            <c>
                <d>Sub Footer Value B</d>
                <e>System generated trash</e>
            </c>
        </r>
        <r>
            <c>
                <d>Sub Footer Tag C</d>
                <e>System generated trash</e>
            </c>
            <c>
                <d>Sub Footer Value C</d>
                <e>System generated trash</e>
            </c>
        </r>
    </footer>
</body>
</roottag>

出力

<?xml version="1.0" encoding="utf-8"?>
<roottag>
  <body>
    <header>
      <HeaderTag>
        <!-- without spaces -->
        <HeaderName>Header Tag</HeaderName>
        <!-- This needs to preserve spaces-->
      </HeaderTag>
      <SubHeaderTagA>
        <!-- without spaces -->
        <HeaderName>Sub Header Tag A</HeaderName>
        <!-- This needs to preserve spaces-->
        <HeaderValue>Sub Header Value A</HeaderValue>
      </SubHeaderTagA>
      <SubHeaderTagB>
        <HeaderName>Sub Header Tag B</HeaderName>
        <HeaderValue>Sub Header Value B</HeaderValue>
      </SubHeaderTagB>
      <SubHeaderTagC>
        <HeaderName>Sub Header Tag C</HeaderName>
        <HeaderValue>Sub Header Value C</HeaderValue>
      </SubHeaderTagC>
    </header>
    <information>
      <r>Body of document</r>
      <r>Appears here but have an XSLT that deals with this</r>
      </information>
      <footer>
        <FooterTag>
          <FooterName>Footer Tag</FooterName>
        </FooterTag>
        <SubFooterTagA>
          <FooterName>Sub Footer Tag A</FooterName>
          <FooterValue>Sub Footer Value A</FooterValue>
        </SubFooterTagA>
        <SubFooterTagB>
          <FooterName>Sub Footer Tag B</FooterName>
          <FooterValue>Sub Footer Value B</FooterValue>
        </SubFooterTagB>
        <SubFooterTagC>
          <FooterName>Sub Footer Tag C</FooterName>
          <FooterValue>Sub Footer Value C</FooterValue>
        </SubFooterTagC>
      </footer>
    </body>
</roottag>

それで、私が見ている問題と私が直面している問題を説明します。

  1. スペースの削除: roottag / body / header / r / c / d内に保持されている値にはスペースが含まれることがあり、多くの場合、スペースが含まれることが多いため、サイト[addLink]の質問から見つけたこれを削除する方法が必要ですが、これも値を置き換えますそのため、プロセスの後半でデータを使用するようになると、出力に必要なスペースがなくなります。
  2. Rを最初の値のみに置き換える: これを行う方法がわかりません。私が試したり調べたりしたことはすべて、2番目の値を値として使用しているようです。私はそれで終わりです。
  3. ヘッダーまたはフッターの名前/値: これが可能である場合でも、私の知識は限られていますか、またはタグごとに個別の一致が必要ですか?

  4. ヘッダーとフッタータグの移動: これを必要な出力に含めていませんが、これを行う必要があると思います-ヘッダータグとフッタータグをbodyタグの外に移動することは可能ですか?したがって、XMLは次のようになります。roottag-header-body-information-/ body-footer /-/ rt

さらに詳しい説明が必要な場合は、お知らせください。

4

2 に答える 2

2

ソース内の要素の内容から要素名を派生させることは、一般的に悪い考えです。スペースを削除することはできますが、他の特殊文字の可能性が常にあり、それらをすべて削除したとしても、意図しない重複が発生する可能性があります。たとえば、1 Tagとを含む 2 つの要素は、両方とも に削除する必要があります。2 TagTag

ただし、次のようなものが機能するはずです。

<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:variable name="allowed">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvxyz_</xsl:variable>

  <xsl:template match="r[c/d]">
    <xsl:variable name="elemName" select="translate(c/d,translate(c/d,$allowed,''),'')" />
    <xsl:element name="{$elemName}">
      <xsl:apply-templates />
    </xsl:element>
  </xsl:template>

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

  <xsl:template match="c[1]/d">
    <HeaderName>
      <xsl:apply-templates />
    </HeaderName>
  </xsl:template>

  <xsl:template match="c[2]/d">
    <HeaderValue>
      <xsl:apply-templates />
    </HeaderValue>
  </xsl:template>

  <xsl:template match="e" />

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

これは、「二重変換」メソッドを使用して、文字列からすべての望ましくない文字を取り除きます。このtranslate関数を使用して、これらの文字を変換する空の文字列を指定することにより、リストからすべての文字を削除できます。これを使用して、文字列からすべての有効な文字を削除し、無効な文字のみを含む文字列を残すことができます。次に、もう一度 translate を使用して、元の文字列からすべての無効な文字を削除します。

本文の外側にヘッダー/フッターが必要な場合は、次のテンプレートを追加してください。

<xsl:template match="roottag">
  <xsl:copy>
    <xsl:apply-templates select="body/header" />
    <xsl:apply-templates select="body" />
    <xsl:apply-templates select="body/footer" />
  </xsl:copy>
</xsl:template>

<xsl:template match="body">
  <xsl:copy>
    <xsl:apply-templates select="information" />
  </xsl:copy>
</xsl:template>

r等号を含むノードを無視するには、" "c\dに一致するテンプレートの下にこのテンプレートを追加します。r[c/d]

<xsl:template match="r[contains(c/d,'=')]" />
于 2012-12-10T13:34:01.193 に答える
1

さて、複数の質問があります!だから複数の答え..できるだけ体系的に書いてみます。そして気軽に質問してください!!

1.最初のステップは、タグ間の余分な不要なスペースを取り除くことです..これを達成するには、XML宣言のすぐ下のヘッダーとして以下の2つのステートメントがあります:

  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

2.次のステップは、IDテンプレートを定義することです! その仕事は、入力からそのまま出力することです(出力しないように命令されたものを除く)

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

3.出力では、要素を見たくありません<r>! したがって、以下の行があります

  <xsl:template match="/roottag/body/header/r
                      |/roottag/body/footer/r">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:template>

これは要素をコピーしません<r>が、子要素に引き継がせます!! 以下に書きます..

<c>4.すべての要素の最初のタグのみをコピーし、出力から<r>残りの<c>ノードを無視したい..そのため、以下のテンプレートオーバーライドを定義します..

  <xsl:template match="/roottag/body/header/r/c
                      |/roottag/body/footer/r/c"/>

これにより、実際に<c>は出力からすべての要素が削除されます! ただし、オーバーライドの下では、最初の<c>要素のみが処理されます!

5.このコードは<Header>、出力で要素を構築するためのものです!

  <xsl:template match="/roottag/body/header/r/c[1]">
    <xsl:variable name="ElementName">
      <xsl:call-template name="RemoveSpaceFromValueD">
        <xsl:with-param name="text" select="d/."/>
        <xsl:with-param name="replace" select="' '"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:element name="{$ElementName}">
      <xsl:element name="HeaderName">
        <xsl:value-of select="d/."/>
      </xsl:element>
      <xsl:if test="ancestor::r != ancestor::header/r[1]">
      <xsl:element name="HeaderValue">
        <xsl:value-of select="e/."/>
      </xsl:element>
      </xsl:if>
    </xsl:element>
  </xsl:template>

このコードを使用することで、異なるテンプレートに対して異なるテンプレートを宣言する必要がなくなります。<header>, <footer> and <subHeaderTag>s

私がここでやっていることは次のとおりです。

  1. RemoveSpaceFromValueDelement からテキストをコピーdし、テキストからスペースを削除して variable に割り当てる新しいテンプレートを呼び出しますElementName
  2. 変数からのその値をElementName使用して、新しい要素を作成します! だから親として持つSub Header Tag Cでしょう<SubHeaderTagC>:)
  3. <d>の値を<HeaderName>!にコピーします。
  4. <d>次から次<c>へコピー<HeaderValue>

6.同様に同じコードを繰り返し<Footer>ます。

  <xsl:template match="/roottag/body/footer/r/c[1]">
    <xsl:variable name="ElementName">
      <xsl:call-template name="RemoveSpaceFromValueD">
        <xsl:with-param name="text" select="d/."/>
        <xsl:with-param name="replace" select="' '"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:element name="{$ElementName}">
      <xsl:element name="FooterName">
        <xsl:value-of select="d/."/>
      </xsl:element>
      <xsl:if test="ancestor::r != ancestor::footer/r[1]">
        <xsl:element name="FooterValue">
          <xsl:value-of select="e/."/>
        </xsl:element>
      </xsl:if>
    </xsl:element>

  </xsl:template>

7.そしてテンプレートRemoveSpaceFromValueD:

  <xsl:template name="RemoveSpaceFromValueD">
    <xsl:param name="text"/>
    <xsl:param name="replace"/>
    <xsl:choose>
      <xsl:when test="contains($text,$replace)">
        <xsl:value-of select="substring-before($text,$replace)"/>
        <xsl:call-template name="RemoveSpaceFromValueD">
          <xsl:with-param name="text" select="substring-after($text,$replace)"/>
          <xsl:with-param name="replace" select="$replace"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>

8. XSLT コード全体は次のようになります。

これをテストしてください!ご不明な点やご不明な点がございましたら、お気軽にお問い合わせください。

<?xml version="1.0" encoding="utf-8"?>
<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:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>


  <xsl:template match="/roottag/body/header/r
                      |/roottag/body/footer/r">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:template>


  <xsl:template match="/roottag/body/header/r/c
                      |/roottag/body/footer/r/c"/>


  <xsl:template match="/roottag/body/header/r/c[1]">
    <xsl:variable name="ElementName">
      <xsl:call-template name="RemoveSpaceFromValueD">
        <xsl:with-param name="text" select="d/."/>
        <xsl:with-param name="replace" select="' '"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:element name="{$ElementName}">
      <xsl:element name="HeaderName">
        <xsl:value-of select="d/."/>
      </xsl:element>
      <xsl:if test="ancestor::r != ancestor::header/r[1]">
        <xsl:for-each select="../c[2]">
          <xsl:element name="HeaderValue">
            <xsl:value-of select="d/."/>
          </xsl:element>
        </xsl:for-each>
      </xsl:if>
    </xsl:element>

  </xsl:template>


  <xsl:template match="/roottag/body/footer/r/c[1]">
    <xsl:variable name="ElementName">
      <xsl:call-template name="RemoveSpaceFromValueD">
        <xsl:with-param name="text" select="d/."/>
        <xsl:with-param name="replace" select="' '"/>
      </xsl:call-template>
    </xsl:variable>

    <xsl:element name="{$ElementName}">
      <xsl:element name="FooterName">
        <xsl:value-of select="d/."/>
      </xsl:element>
      <xsl:for-each select="../c[2]">
        <xsl:element name="FooterValue">
          <xsl:value-of select="d/."/>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>

  </xsl:template>


  <xsl:template name="RemoveSpaceFromValueD">
    <xsl:param name="text"/>
    <xsl:param name="replace"/>
    <xsl:choose>
      <xsl:when test="contains($text,$replace)">
        <xsl:value-of select="substring-before($text,$replace)"/>
        <xsl:call-template name="RemoveSpaceFromValueD">
          <xsl:with-param name="text" select="substring-after($text,$replace)"/>
          <xsl:with-param name="replace" select="$replace"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <xsl:value-of select="$text"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>


</xsl:stylesheet>
于 2012-12-10T13:18:10.720 に答える