XSLT和文本格式

时间:2012-10-30 13:38:00

标签: xml templates xslt text formatting

我正在制作一个XSLT模板,以便将XML转换为LaTeX(然后是HTML)。我认为XSLT不是为此而制作的,但它确实有效。我唯一的问题是文本格式:如果在某些文本行中,我想使用粗体斜体字词,则语法为“< i>< / i >”中例如,在HTML中,但在LaTeX中是“\ textit {}”。

一种解决方案是将“i”声明为模板,但我不知道是否可以“自动”为每个被加载的文本块应用它(我不想在所有模板中明确地调用它)< / p>

抱歉,我是这项技术的新手,可能存在非常简单的解决方案,但Google这次没有帮助我。

任何建议都将受到赞赏。

编辑:例如:

Xsl:

<xsl:template match="one">
<xsl:apply-templates select="two"/>
</xsl:template>

XML:

<one>
<two>Some text with <i>italic</i> words</two>
</one>

期望的输出:

"Some text with \textit{italic} words"

我不想这样做:

<xsl:apply-templates select="i"/>

在我的所有模板中

所以我正在寻找一种方法来“全局”应用“i”模板。

2 个答案:

答案 0 :(得分:3)

就这么简单

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="i">
     <xsl:text>\textit{</xsl:text>
     <xsl:apply-templates/>
     <xsl:text>}</xsl:text>
 </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<one>
    <two>Some text with <i>italic</i> words</two>
</one>

产生了想要的正确结果:

Some text with \textit{italic} words

<强>解释

XSLT处理模型使用多个built-in templates,如果XSLT程序员不提供与特定节点匹配的模板,则使用该"push-style"提供任何XML文档的默认处理。

特别是,任何元素节点的内置模板,只需发出<xsl:apply-templates/>,以便模板应用于其所有子节点。

任何文本节点的内置模板都是将此文本节点复制到输出。

这意味着我们不需要为节点提供任何模板,如果它必须与相应的内置模板完全相同。

只留下i元素 - 所以我们提供了匹配i的模板 - 它只是用“\ textit {”和“}”来处理其子元素的结果。

请注意

完全可以表达复杂的转换,而无需指定单个<xsl:apply-templates><xsl:call-template><xsl:for-each><xsl:choose><xsl:when>,{{1 }和<xsl:otherwise>

这称为"pull-style",而不是{{3}} ,其中广泛使用了其中一条或任何一条指令。

“推”式表达了问题的最具声明性的解决方案,而“拉式”转换表达了更“必要”的解决方案。

这是XSLT的精神,并建议尽可能多地生成“推送”代码

答案 1 :(得分:0)

编辑:我现在最后添加了一个完整的XSL,基于OP的XML和XSL

这只是一个假设,因为---正如Dimitre在评论中所指出的那样 - 我们无法准确地看到你的XSL,输入或所需的输出。但是,你可能想要这样的东西。

<xsl:template match="//i">
   <xsl:text>\textit{</xsl:text>
   <xsl:apply-templates select="@*|node()"/>
   <xsl:text>}</xsl:text>
</xsl:template>


  <!-- or with namespace -->

<xsl:template match="//*[namespace-uri()='http://www.w3.org/1999/xhtml' and local-name()='i']">
   <xsl:text>\textit{</xsl:text>
   <xsl:apply-templates select="@*|node()"/>
   <xsl:text>}</xsl:text>
</xsl:template>



<!-- assumes there is a copy happening like: -->
<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

将类似的模板添加到XSL中,应该使其对输入中找到的每个 执行。

输出(当放入只复制HTML文档的XSL时)看起来像:

<!-- before -->
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>test</title>
  </head>
  <body>
    <p>
      <i>This is Only a Test</i>
    </p>
  </body>
</html>


<!-- after -->
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>test</title>
  </head>
  <body>
    <p>
      \textit{This is Only a Test}
    </p>
  </body>
</html>

如果你给我们更多,我会更新这个更具体。

编辑:基于OP代码的完整示例(最终提供)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/">
    <xsl:apply-templates select="one"/>
  </xsl:template>

  <xsl:template match="one">
    <xsl:apply-templates select="two"/>
  </xsl:template>

  <xsl:template match="//i">
    <xsl:text>\textit{</xsl:text>
    <xsl:apply-templates select="@*|node()"/>
    <xsl:text>}</xsl:text>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>