我有一个相当简单的xsl样式表,用于将定义html的xml文档转换为html格式(请不要问为什么,这只是我们必须这样做的方式…)
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="HtmlElement">
<xsl:element name="{ElementType}">
<xsl:apply-templates select="Attributes"/>
<xsl:value-of select="Text"/>
<xsl:apply-templates select="HtmlElement"/>
</xsl:element>
</xsl:template>
<xsl:template match="Attributes">
<xsl:apply-templates select="Attribute"/>
</xsl:template>
<xsl:template match="Attribute">
<xsl:attribute name="{Name}">
<xsl:value-of select="Value"/>
</xsl:attribute>
</xsl:template>
当我遇到这一小段需要转换的HTML时,问题就出现了:
<p>
Send instant ecards this season <br/> and all year with our ecards!
</p>
中间的<br/>
打破了转换的逻辑,只给了我段落块的前半部分:Send instant ecards this season <br></br>
。要转换的XML看起来像:
<HtmlElement>
<ElementType>p</ElementType>
<Text>Send instant ecards this season </Text>
<HtmlElement>
<ElementType>br</ElementType>
</HtmlElement>
<Text> and all year with our ecards!</Text>
</HtmlElement>
建议吗?
你可以简单地为Text元素添加一个新规则,然后匹配HTMLElements和Text:
<xsl:template match="HtmlElement">
<xsl:element name="{ElementName}">
<xsl:apply-templates select="Attributes"/>
<xsl:apply-templates select="HtmlElement|Text"/>
</xsl:element>
</xsl:template>
<xsl:template match="Text">
<xsl:value-of select="." />
</xsl:template>
您可以使样式表更通用一点,以便通过调整HtmlElement
的模板来处理额外的元素,以确保它首先将模板应用于Attributes
元素,然后通过在xsl:apply-templates
的select属性中使用谓词过滤器将模板应用于除 Attributes
和HtmlElement
元素之外的所有元素。
内置模板将匹配Text
元素并将text()
复制到输出中。
同样,当前已声明的根节点模板(即match="/"
)可以被删除。它只是重新定义已经由内置模板规则处理的内容,并且不做任何事情来改变行为,只是使您的样式表混乱。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<!-- <xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>-->
<xsl:template match="HtmlElement">
<xsl:element name="{ElementType}">
<xsl:apply-templates select="Attributes"/>
<!--apply templates to all elements except for ElementType and Attributes-->
<xsl:apply-templates select="*[not(self::Attributes|self::ElementType)]"/>
</xsl:element>
</xsl:template>
<xsl:template match="Attributes">
<xsl:apply-templates select="Attribute"/>
</xsl:template>
<xsl:template match="Attribute">
<xsl:attribute name="{Name}">
<xsl:value-of select="Value"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>