2

<a>XML 1.0を使用して、各タグ内のコンテンツを説明ノード内の文字数制限20にトリミングする必要があります。これがXMLです

  <description> 
       This is text <a href="http://stackoverflow.com/posts/14718323/edit">http://stackoverflow.com/posts/14718323/edit</a>. 
       Also here is more text than we have another 
       <a href="http://stackoverflow.com/posts/14718323/edit">http://stackoverflow.com/posts/14718323/edit</a>.
  </description>

私がそれを変えるために必要なのはこれです:

  <description> 
       This is text <a href="http://stackoverflow.com/posts/14718323/edit">http://stacko</a>. 
       Also here is more text than we have another 
       <a href="http://stackoverflow.com/posts/14718323/edit">http://stacko</a>.
  </description>

ほとんどのロジックを実行できますが、説明ノードを検索して「each」<a>を変換する「for-each」を実行するのに問題があります。

これは意味がありますか?助けていただければ幸いです。

**編集2/7/13 *

ここで提供された回答に基づいて、私は今ここにいます。

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

   <xsl:template match="a">
    <a href="{@href}">
       <xsl:value-of select="substring(normalize-space(),1,20)"/>
    </a>
   </xsl:template>

問題は、XSLに複数のテンプレートがあるため、「apply-templates」が機能しないことです。テンプレートを具体的に呼び出す必要があるので、「call-template」がルートになると思いました。「call-template」の唯一の問題は、参照する特定のXMLノードを指定する方法がわからないことです。これが私がこれまでにそれをハックした方法です(動作しません):

    <xsl:template match="/">
      <xsl:call-template name="trim_text"/>
     </xsl:template>

    <xsl:template name="trim_text" match="//description">
     <a href="{@href}">
       <xsl:value-of select="substring(normalize-space(),1,20)"/>
     </a>
    </xsl:template>

<xsl:template match="/">これははるかに大きな関数で行われるため、最初の「call-template」はにある必要があります。だから私は3つのものが必要です:

1)XMLの内容との一貫性を保つためのHREF

<a>2) 20pxにトリミングされるタグ間のテキスト

3)XMLで多くの変換を行うはるかに大きなxslテンプレート内からこのテンプレートを呼び出す必要があります。これは約7回のテンプレート呼び出しになります。

4

3 に答える 3

2

この変換は、の使用を回避し、xsl:attributeより適切にフォーマットされ、より読みやすくなります。

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

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

 <xsl:template match="a[@href]">
  <a href="{substring(@href,1,20)}">
    <xsl:apply-templates select="@*[not(name()='href')]|node()"/>
  </a>
 </xsl:template>
</xsl:stylesheet>

このXMLドキュメントに適用した場合:

<root>
    <description>
            This is text 
        <a href="http://www.longlink/morelink/page/anotherpage">Link Here</a>.
            Also here is more text than we have another
        <a href="link-style:null">Link Here</a>.
    </description>
</root>

必要な正しい結果を生成します。

<root>
   <description>
            This is text 
        <a href="http://www.longlink/">Link Here</a>.
            Also here is more text than we have another
        <a href="link-style:null">Link Here</a>.
    </description>
</root>

説明

  1. IDルール-このテンプレートが実行用に選択されているすべてのノードをそのままコピーします。

  2. AVT(属性値テンプレート)の使用。

于 2013-02-06T03:42:51.967 に答える
1

OPのコメントで改訂された質問に、文字を20文字に制限する必要があるという回答。

サブストリング関数を試して、最初の20文字だけを返します。

<xsl:value-of select="substring(.,1,20)"/>

より完全な答えは次のとおりです。

このXSLT1.0変換:

    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>  
        </xsl:template>
        <xsl:template match="a/@href">
            <xsl:attribute name="href"><xsl:value-of select="substring(.,1,20)"/></xsl:attribute>
        </xsl:template>
    </xsl:stylesheet>

このXMLドキュメントに適用する場合:

    <root>
        <description> 
            This is text <a href="http://www.longlink/morelink/page/anotherpage">Link Here</a>. 
            Also here is more text than we have another 
            <a href="link-style:null">Link Here</a>.
        </description>
    </root>

結果は目的の結果になります(最初のhref属性の短縮に注意してください)。

    <root>
        <description> 
            This is text <a href="http://www.longlink/">Link Here</a>. 
            Also here is more text than we have another 
            <a href="link-style:null">Link Here</a>.
        </description>
    </root>

説明:

  • ID変換(最初のテンプレート)は、すべてのノードと属性を結果ツリーにコピーします。
  • 2番目のテンプレートは、hrefの最初の20文字のみをコピーします
  • for-eachがないことにも注意してください。むしろ、テンプレートルールとapply-templatesを使用しています。可能な場合は、テンプレートを使用する必要があります。
于 2013-02-05T23:55:42.140 に答える
1

問題は、XSLに複数のテンプレートがあるため、「apply-templates」が機能しないことです。テンプレートを具体的に呼び出す必要があるので、「call-template」がルートになると思いました。「call-template」の唯一の問題は、参照する特定のXMLノードを指定する方法がわからないことです。

テンプレートモードはあなたが探しているものかもしれません

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

  <xsl:template match="/">
    <!-- do some other stuff ... -->

    <!-- handle the description -->
    <xsl:apply-templates select=".//description" mode="description" />

    <!-- more other stuff here -->
  </xsl:template>

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

  <xsl:template match="a" mode="description">
    <xsl:copy>
      <xsl:apply-templates select="@*" mode="description" />
      <xsl:value-of select="substring(., 1, 20)" />
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

でモードを指定すると、各ノードに適用するテンプレートを見つけるときに、同じモードでマークされたテンプレートのみが考慮されます(さらに、すべての要素ノードに一致し、同じモードを使用apply-templatesする子にテンプレートを再帰的に適用するデフォルトの暗黙的なテンプレートですが、 IDテンプレートがあるため、ここでは適用されません)。この要素のサンプルテンプレートでは、他のタグを含むリンクは許可されていません。たとえば、a

<a href="#">This is a <b>very</b> long piece of text used as an example</a>

になります

<a href="#">This is a very long </a>

このようなマークアップを保持したい場合は、はるかに複雑になります。あなたはの明白なアプローチでそれを行うことはできません

<xsl:template match="a//text()" mode="description">
  <xsl:value-of select="substring(., 1, 20)"/>
</xsl:template>

これは、各テキストノードを個別に処理し、生成するためです。

<a href="#">This is a <b>very</b> long piece of text </a>

(「これは」と「非常に」はすでに20文字より短いため、「長いテキスト」は「...として使用される長いテキスト」の20文字に切り捨てられます)

于 2013-02-07T16:00:19.287 に答える