我需要在xslt中查找并替换实体。我需要在不使用模板匹配的情况下执行此操作。
假设我的xml像这样,
<root>
<p>Master's</p>
<p><blockFixed type="quotation"><p>let's</p></blockFixed></p>
<p>student's<featureFixed id=1/></p>
<p><blockFixed type="quotation"><p>nurse's</p></blockFixed></p>
<p>Master's</p>
</root>
我需要将'
更改为’
,因此输出应该是这样的,
<root>
<p>Master<apos>’</apos>s</p>
<p><blockFixed type="quotation"><p>let<apos>’</apos>s</p></blockFixed></p>
<p>student<apos>’</apos>s<featureFixed id=1/><\p>
<p><blockFixed type="quotation"><p>nurse<apos>’</apos>s</p></blockFixed></p>
<p>Master's</p>
</root>
我使用模板匹配p
使用了替换方法,但之后我无法对blockfixed
等其他标签执行任何操作。所以请建议简单的xslt来做到这一点。
我使用了以下xslt,
<xsl:template match="p">
<xsl:copy>
<xsl:apply-templates select="current()/node()" mode="replace"/>
</xsl:copy>
</xsl:template>
<xsl:template match="text()" mode="replace">
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="from">'</xsl:with-param>
<xsl:with-param name="to" select="'’'"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="replace-string">
<xsl:param name="text"/>
<xsl:param name="from"/>
<xsl:param name="to"/>
<xsl:choose>
<xsl:when test="contains($text, $from)">
<xsl:variable name="before" select="substring-before($text, $from)"/>
<xsl:variable name="after" select="substring-after($text, $from)"/>
<xsl:variable name="prefix" select="concat($before, $to)"/>
<xsl:copy-of select="$before"/>
<Apos>
<xsl:copy-of select="$to"/>
</Apos>
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="$after"/>
<xsl:with-param name="from" select="$from"/>
<xsl:with-param name="to" select="$to"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
提前感谢。
答案 0 :(得分:1)
问题在于您的模板与 p 元素匹配
<xsl:template match="p">
<xsl:copy>
<xsl:apply-templates select="current()/node()" mode="replace"/>
</xsl:copy>
</xsl:template>
特别是,您使用模式。虽然您选择 p 元素的所有子节点,但您只为text()节点提供了匹配模板,模式为替换。这意味着不会挑选出所有其他元素,因此忽略 blockFixed 。
相反,从XSLT中删除与 p 匹配的上述模板,并替换以下行:
<xsl:template match="text()" mode="replace">
有了这个
<xsl:template match="p/text()">
这假设您在XSLT中构建了身份转换。这是XSLT的删节版本
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p/text()">
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="from">'</xsl:with-param>
<xsl:with-param name="to" select="'&rsquo;'"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="replace-string">
<xsl:param name="text"/>
<xsl:param name="from"/>
<xsl:param name="to"/>
<xsl:choose>
<xsl:when test="contains($text, $from)">
<xsl:variable name="before" select="substring-before($text, $from)"/>
<xsl:variable name="after" select="substring-after($text, $from)"/>
<xsl:variable name="prefix" select="concat($before, $to)"/>
<xsl:copy-of select="$before"/>
<Apos>
<xsl:value-of select="$to" disable-output-escaping="yes"/>
</Apos>
<xsl:call-template name="replace-string">
<xsl:with-param name="text" select="$after"/>
<xsl:with-param name="from" select="$from"/>
<xsl:with-param name="to" select="$to"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 1 :(得分:0)
你提到的replace
方法只在XSLT和XPath 2.0中可用,所以我假设你使用的是XSLT 2.0处理器?您是否知道XSLT在具有Unicode字符串值的纯文本节点的数据模型上运行,因此实体引用不在该数据模型中建模。并且要将转换结果中的字符强制输出为实体引用而不是Unicode字符,您需要XSLT 2.0字符映射。
所以你可以做的是使用analyze-string处理文本节点,例如
<xsl:template match="p//text()">
<xsl:analyze-string select="." regex="'">
<xsl:matching-substring>
<apos>’</apos>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
输出带有右引号字符apos
的{{1}}元素,然后您需要添加一个字符映射,以确保将此字符替换为其实体引用。
我意识到尽管你提出要求,我还是使用了一个模板来解决这个问题。但是,您需要将我的建议合并到更复杂的样式表中,在’
元素的模板中执行apply-templates
,所以也许您可以这样做。