我正在使用正在应用于HTML文档的XSL转换。相关的HTML示例:
<div class="row home-row">
<p>Hello</p>
</div>
我选择与之匹配的项目与以下XSL(运行良好):
<xsl:template match="//*[contains(concat(' ', normalize-space(@class), ' '), ' row ')]" priority="1">
然后,如果我之前检查的条件匹配,我将“row”替换为“row-fluid”,如下所示:
<xsl:variable name="original-row-class" select="string(@class)" />
<xsl:variable name="row-class">
<xsl:call-template name="replace">
<xsl:with-param name="text" select="$original-row-class" />
<xsl:with-param name="replace" select="' row '" />
<xsl:with-param name="by" select="' row-fluid '" />
</xsl:call-template>
</xsl:variable>
<xsl:copy>
<xsl:attribute name="class"><xsl:value-of select="$row-class" /></xsl:attribute>
<xsl:apply-templates select="@*[local-name() != 'class']|node()[local-name() != 'class']"/>
</xsl:copy>
这也很有效,除非它将所有提及的“row”替换为“row-fluid”,即使它们位于“home-row”内。我想要做的是将“行”类更改为“row-fluid”,但在执行此操作时忽略“home-row”类。这可能吗?
我应该提到我被锁定在XSLT 1.0中。
更新:在下面添加替换模板(应该早点考虑过这个!):
<xsl:template name="replace">
<xsl:param name="text" />
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)" />
<xsl:value-of select="$by" />
<xsl:call-template name="replace">
<xsl:with-param name="text" select="substring-after($text,$replace)" />
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
谢谢, 乔纳森
答案 0 :(得分:3)
我认为您必须将类字符串拆分为带有recurcive模板调用的单词。 e.g。并比较/替换每个单词。
好的,这是一个基于递归方法的解决方案。
<xsl:template match="test" >
<xsl:variable name ="new_class">
<xsl:call-template name="replace_words">
<xsl:with-param name="replace" select="'xx'"/>
<xsl:with-param name="by" select="'yyy'"/>
<xsl:with-param name="words" select="'xx xx-a xx-b xx xx'"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="$new_class"/>
</xsl:template>
<xsl:template name="replace_words">
<xsl:param name="replace"/>
<xsl:param name="by"/>
<xsl:param name="words"/>
<xsl:choose>
<xsl:when test="contains($words,' ')">
<!-- try replace first word-->
<xsl:call-template name="replace_words">
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
<xsl:with-param name="words" select="substring-before($words,' ')"/>
</xsl:call-template>
<!-- dlimeter -->
<xsl:text> </xsl:text>
<xsl:call-template name="replace_words">
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
<xsl:with-param name="words" select="substring-after($words,' ')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$replace = $words">
<xsl:value-of select="$by"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$words"/>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
只需对原始转换进行一些修改,它现在可以按照想要的方式运行 - 不需要扩展功能:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[contains(concat(' ', @class, ' '), ' row ')]">
<xsl:variable name="original-row-class" select="string(@class)" />
<xsl:variable name="row-class">
<xsl:call-template name="replace">
<xsl:with-param name="text" select=
"concat(' ', $original-row-class, ' ')" />
<xsl:with-param name="replace" select="' row '" />
<xsl:with-param name="by" select="' row-fluid '" />
</xsl:call-template>
</xsl:variable>
<xsl:copy>
<xsl:attribute name="class">
<xsl:value-of select="normalize-space($row-class)" />
</xsl:attribute>
<xsl:apply-templates select=
"@*[local-name() != 'class']|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template name="replace">
<xsl:param name="text" />
<xsl:param name="replace" />
<xsl:param name="by" />
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)" />
<xsl:value-of select="$by" />
<xsl:call-template name="replace">
<xsl:with-param name="text" select="substring-after($text,$replace)" />
<xsl:with-param name="replace" select="$replace" />
<xsl:with-param name="by" select="$by" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text" />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
应用于提供的XML文档时:
<div class="row home-row">
<p>Hello</p>
</div>
产生了想要的正确结果:
<div class="row-fluid home-row">
<p>Hello</p>
</div>
答案 2 :(得分:0)
这似乎对我有用。跳过分隔线并将其全部粘贴在下面。
虽然我在下面的答案发布之前就已经开始工作了,但我确实尝试了这个,但它没有立即起作用。我想在这一点上我会好奇这是否有一些特别错误,但我会坚持下去。至少在下面给出了很棒的方向。
<xsl:template match="//*[contains(concat(' ', normalize-space(@class), ' '), ' row ')]" priority="1">
<xsl:param name="separator" select="' '" />
<xsl:variable name="class-array">
<xsl:attribute name="name">
<xsl:value-of select="$original-row-class"/>
</xsl:attribute>
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="$original-row-class" />
</xsl:call-template>
</xsl:variable>
<xsl:variable name="items" select="ext:node-set($class-array)" />
<xsl:variable name="row-class">
<xsl:for-each select="$items/item">
<xsl:choose>
<xsl:when test="position() = 1">
<xsl:choose>
<xsl:when test=". = 'row'">row-fluid</xsl:when>
<xsl:otherwise><xsl:value-of select="." /></xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test=". = 'row'"><xsl:value-of select="concat($separator, 'row-fluid') "/></xsl:when>
<xsl:otherwise><xsl:value-of select="concat($separator, .) "/></xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<xsl:copy>
<xsl:attribute name="class"><xsl:value-of select="$row-class" /></xsl:attribute>
<xsl:value-of select="original-row-class" />
<xsl:apply-templates select="@*[local-name() != 'class']|node()[local-name() != 'class']"/>
</xsl:copy>
</xsl:template>
<xsl:template name="tokenize">
<xsl:param name="text" select="."/>
<xsl:param name="sep" select="' '"/>
<xsl:choose>
<xsl:when test="not(contains($text, $sep))">
<item>
<xsl:value-of select="normalize-space($text)"/>
</item>
</xsl:when>
<xsl:otherwise>
<item>
<xsl:value-of select="normalize-space(substring-before($text, $sep))"/>
</item>
<xsl:call-template name="tokenize">
<xsl:with-param name="text" select="substring-after($text, $sep)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>