0

我有 XML 树:

<text>
    <plain>abcd<c>efgh</c>ijklm</plain>
    <plain>nopq<c>rst</c>uvw<c>xyz</c></plain>
    <rp><first><c>asdasd</c>asf</first><second>asdasd</second></rp>
    <plain>aaaaa<c>bbbb</c>ccccc<c>xyz</c></plain>
</text>

然后我的 XSLT 样式表中有代码($product_text 包含上面的树):

<xsl:template name="text_list">
<xsl:if test="$text_count &gt; 0">
    <xsl:apply-templates mode="text_item" select="$product_text/text">
        <xsl:sort select="@rating" order="descending" data-type="number" />
    </xsl:apply-templates>
</xsl:if>
</xsl:template>

<xsl:template mode="text_item" match="*">
    <div class="cmp-post">
        <xsl:copy-of select="./*" />
    </div>
</xsl:template>

此片段按原样复制所有树。但我需要像这样替换/修改所有“c”节点:

<c>efgh</c>
to
<cmp attr="efgh">efgh</c>

<c>rst</c>
to
<cmp attr="rst">rst</c>
etc

(已编辑)我期望的结果:

<div class="cmp-post">
    <plain>abcd<c attr="efgh">efgh</c>ijklm</plain>
    <plain>nopq<c attr="rst">rst</c>uvw<c attr="xyz">xyz</c></plain>
    <rp><first><c attr="asdasd">asdasd</c>asf</first><second>asdasd</second></rp>
    <plain>aaaaa<c attr="bbbb">bbbb</c>ccccc<c attr="xyz">xyz</c></plain>
</div>

我应该如何修改 text_item 模板?

4

1 回答 1

1

Basically, you want to do apply-templates instead of copy-of. copy-of just copies the node; it doesn't do template matching and invocation on the copied elements.

As such, you'll need a few additional templates to get what you want.

<!-- Copy attributes as-is -->
<xsl:template match="@*" mode="text_item">
    <xsl:copy-of select="."/>
</xsl:template>

<!-- By default, copy element and text as-is then apply matching on children -->
<xsl:template match="node()" mode="text_item">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" mode="text_item"/>
    </xsl:copy>
</xsl:template>

<!-- For 'text' elements, use div instead of direct copy -->
<xsl:template match="text" mode="text_item">
    <div class="cmp-post">
        <xsl:apply-templates mode="text_item" />
    </div>
</xsl:template>

<xsl:template match="c" mode="text_item">
    <xsl:copy>
        <xsl:attribute name='attr'><xsl:value-of select="."/></xsl:attribute>
        <xsl:apply-templates mode="text_item" />
    </xsl:copy>
</xsl:template>

(Note that the @* template is just for completeness. Your current input doesn't have any attributes, but if it did, this would copy them to the output.)

Running the above templates on your input with this as a caller

<xsl:template match="/">
    <xsl:apply-templates select="." mode="text_item">
  <xsl:sort select="@rating" order="descending" data-type="number" />
    </xsl:apply-templates>
</xsl:template>

gives the output

<div class="cmp-post">
    <plain>abcd<c attr="efgh">efgh</c>ijklm</plain>
    <plain>nopq<c attr="rst">rst</c>uvw<c attr="xyz">xyz</c></plain>
    <rp><first><c attr="asdasd">asdasd</c>asf</first><second>asdasd</second></rp>
    <plain>aaaaa<c attr="bbbb">bbbb</c>ccccc<c attr="xyz">xyz</c></plain>
</div>

It should be the same when called against a node variable.

于 2013-04-16T17:26:16.383 回答