首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用XSLT1.0将XML内容中的WordML标记替换为wordML格式化标记

使用XSLT1.0将XML内容中的WordML标记替换为wordML格式化标记
EN

Stack Overflow用户
提问于 2008-10-24 16:18:13
回答 4查看 8.1K关注 0票数 1

我正在从一个xml文件创建一个WordML文档,该文件的元素有时包含html格式的文本。

代码语言:javascript
复制
<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字符串插入的情况下开始新的运行。这个是可能的吗?

EN

回答 4

Stack Overflow用户

发布于 2008-10-30 17:38:23

使用WordML是很棘手的。使用XSLT将任意XML转换为WordML时的一个技巧是,在处理块时不要担心文本运行,而是直接创建一个与text()节点匹配的模板,并在那里创建文本运行。事实证明,Word并不关心您是否嵌套文本运行,这使得问题更容易解决。

代码语言:javascript
复制
   <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并不关心。如果使用这种技术,需要注意不要将模板应用到段落之间的空白处,因为它会触发文本模板并创建脱离上下文的运行。

票数 3
EN

Stack Overflow用户

发布于 2008-10-27 06:57:33

如果我能理解你的问题,我很可能会帮你。html是在CDATA部分中,还是被解析为输入文档的一部分(因此是格式良好的XML)?既然你谈到了“文本替换”,我就假设你把“html格式的内容”当作一个单独的字符串(CDATA),因此需要一个递归的调用模板函数来执行字符串替换。使用XSL匹配模板完成现在所做的工作的唯一方法是将html部分作为解析文档(输入文档)的一部分。在这种情况下,您只需匹配b标记并将其替换为适当的输出(同样:假设始终可以将其解析为有效的XML)。你的问题现在已经转移了.因为(如果我正确理解了您的问题)您要做的是关闭w:tw:r元素,然后“重新打开”它们…这很困难,因为(正如您可能怀疑的那样)在XSLT中很难做到这一点(不能在模板A中创建一个元素,然后在模板B中关闭它)。你必须开始处理未转义的输出等,才能实现这一点。我现在做了很多假设,但这里有一个小例子来帮助你:

input.xml

代码语言:javascript
复制
<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

代码语言:javascript
复制
<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="'&lt;/w:t>&lt;/w:r>&lt;w:r>&lt;w:rPr>&lt;w:b/>&lt;/w:rPr>&lt;w:t>'" disable-output-escaping="yes" />
  <xsl:apply-templates select="@*|node()"/>
  <xsl:value-of select="'&lt;/w:t>&lt;/w:r>&lt;w:r>&lt;w:t>'" disable-output-escaping="yes" />
</xsl:template>

现在正在运行

代码语言:javascript
复制
xalan input.xml convert_html.xsl

产生

代码语言:javascript
复制
<?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>

我猜这就是你想要的。

希望这能对你有所帮助。

票数 0
EN

Stack Overflow用户

发布于 2008-10-27 14:30:45

根据您的描述,听起来您可以解析嵌入的html。如果是这样的话,简单地应用模板就可以做到你想要的效果。输出中的wordML可能不正确,但希望这会有所帮助。

示例输入:

代码语言:javascript
复制
<text>
  <para>
    Test for paragraph 1
  </para>
  <para>
    Test for <b>paragraph 2</b>
  </para>
</text>

转换:

代码语言:javascript
复制
<?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> 

结果:

代码语言:javascript
复制
<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>
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/234215

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档