我正在从xml文件创建一个WordML文档,其元素有时包含html格式的文本。
<w:p>
<w:r>
<w:t> html formatted content is in here taken from xml file! </w:t>
</w:r>
</w:p>
这就是我的模板的设置方式。我有一个递归调用模板函数,可以对源xml内容进行文本替换。当遇到“<b>
”标记时,我在CDATA中输出一个包含“</w:t></w:r><w:r><w:rPr><w:b/></w:rPr><w:t>
”的字符串,以关闭当前运行并启动启用粗体格式的新运行。当它到达“</b>
”标记时,会将其替换为以下CDATA字符串“</w:t></w:r><w:r><w:t>
”。
我想要做的是使用XSL关闭run标记并开始新的运行而不使用CDATA字符串插入。这可能吗?
答案 0 :(得分:3)
使用WordML很棘手。使用XSLT将任意XML转换为WordML时的一个提示是不要担心处理块时的文本运行,而是创建一个直接匹配text()节点的模板,并在那里创建文本。事实证明,Word并不关心你是否嵌套文本运行,这使问题更容易解决。
<xsl:template match="text()" priority="1">
<w:r>
<w:t>
<xsl:value-of select="."/>
</w:t>
</w:r>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:apply-templates select="@*|node()"/>
</xsl:template>
<xsl:template match="para">
<w:p>
<xsl:apply-templates select="text() | *" />
</w:p>
</xsl:template>
<xsl:template match="b">
<w:r>
<w:rPr>
<w:b />
</w:rPr>
<w:t><xsl:apply-templates /></w:t>
</w:r>
</xsl:template>
这避免了将标记作为转义文本直接插入的错误XSLT技术。您最终会将粗体标记作为嵌套文本运行,但正如我所说,Word不会在意。如果您使用此技术,则需要注意不要将模板应用于段落之间的空白区域,因为它会触发文本模板并创建一个上下文运行。
答案 1 :(得分:0)
如果我理解你的问题,我很可能会帮助你...是CDATA部分中的html还是作为输入文档的一部分解析(因此格式良好的XML)?
由于您谈到'文本替换',我将假设您将'html格式化内容'视为单个字符串(CDATA),因此需要一个递归调用模板函数来执行字符串替换。您将能够使用XSL匹配模板来执行您现在正在执行的操作的唯一方法是创建已解析文档(输入文档)的html部分。在这种情况下,您可以匹配b
标记并将其替换为适当的输出(同样:这假设它始终可以解析为有效的XML)。你的问题现在已经改变了...因为(如果我理解你的问题正确)你要做的就是关闭w:t
和w:r
元素,然后'重新打开'它们......这是很难,因为它(你可能怀疑)很难在XSLT中很好地做到这一点(你不能只在模板A中创建一个元素,然后在模板B中关闭它)。你必须开始搞乱未转义的输出等才能实现这一点。我现在已经做了很多假设,但这里有一个小例子来帮助你:
input.xml中
<doc xmlns:w="urn:schemas-microsoft-com:office:word">
<w:p>
<w:r>
<w:t>before<b>bold</b>after</w:t>
</w:r>
</w:p>
</doc>
convert_html.xsl
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/doc/w:p/w:r/w:t//b">
<xsl:value-of select="'</w:t></w:r><w:r><w:rPr><w:b/></w:rPr><w:t>'" disable-output-escaping="yes" />
<xsl:apply-templates select="@*|node()"/>
<xsl:value-of select="'</w:t></w:r><w:r><w:t>'" disable-output-escaping="yes" />
</xsl:template>
正在运行
xalan input.xml convert_html.xsl
产生
<?xml version="1.0" encoding="UTF-8"?><doc xmlns:w="urn:schemas-microsoft-com:office:word">
<w:p>
<w:r>
<w:t>before</w:t></w:r><w:r><w:rPr><w:b/></w:rPr><w:t>bold</w:t></w:r><w:r><w:t>after</w:t>
</w:r>
</w:p>
</doc>
我猜你想要的是什么。
希望这对你有所帮助。
答案 2 :(得分:0)
根据您的描述,听起来您可以解析嵌入的html。如果是这样,只需应用模板就可以做到你想要的。输出中的wordML可能不正确,但希望这会有所帮助。
示例输入:
<text>
<para>
Test for paragraph 1
</para>
<para>
Test for <b>paragraph 2</b>
</para>
</text>
变换:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:w="http://foo">
<xsl:template match="/">
<w:p>
<w:r>
<xsl:apply-templates/>
</w:r>
</w:p>
</xsl:template>
<xsl:template match="para">
<w:t>
<xsl:apply-templates/>
</w:t>
</xsl:template>
<xsl:template match="b">
<w:rPr>
<w:b/>
</w:rPr>
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
结果:
<w:p xmlns:w="http://foo">
<w:r>
<w:t>
Test for paragraph 1
</w:t>
<w:t>
Test for <w:rPr><w:b /></w:rPr>paragraph 2
</w:t>
</w:r>
</w:p>
答案 3 :(得分:0)
完全完成HTML&gt; WordML我推荐您编辑的代码版本:
<xsl:template match="Body"><xsl:apply-templates select="p"/></xsl:template>
<xsl:template match="text()" priority="1"><w:r><w:t><xsl:value-of select="."/></w:t></w:r></xsl:template>
<xsl:template match="@*|node()"><xsl:apply-templates select="@*|node()"/></xsl:template>
<xsl:template match="p"><w:p><xsl:apply-templates select="text() | *" /></w:p></xsl:template>
<xsl:template match="b"><w:r><w:rPr><w:b /></w:rPr><xsl:apply-templates /></w:r></xsl:template>
<xsl:template match="i"><w:r><w:rPr><w:i /></w:rPr><xsl:apply-templates /></w:r></xsl:template>
<xsl:template match="u"><w:r><w:rPr><w:u w:val="single" /></w:rPr><xsl:apply-templates /></w:r></xsl:template>
假设您的HTML已包含在标记
中的XMl中