1

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

一种解决方案是将“i”声明为模板,但我不知道是否可以为每个遇到的文本块“自动”应用它(我不想在所有模板中显式调用它)

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

任何建议将不胜感激。

编辑:例如:

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”模板的方法。

4

2 回答 2

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 处理模型使用许多内置模板,如果 XSLT 程序员不提供与特定节点匹配的模板,则使用这些模板提供对任何 XML 文档的默认处理。

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

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

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

只剩下一个i元素——所以我们提供了一个模板匹配i——它只是用“\textit{”和“}”包围了处理它的子元素的结果。

请注意

完全有可能在不指定单个<xsl:apply-templates><xsl:call-template><xsl:for-each><xsl:choose><xsl:when>和的情况下表达复杂<xsl:otherwise>的变换<xsl:if>

这被称为“推式” ,与广泛使用这些指令中的一个或任何一个的“拉式”相反。

“push”风格表达了对问题的最具声明性的解决方案,而“pull-style”转换表达了更加“命令式”的解决方案。

它符合 XSLT 的精神,并建议始终尝试生成尽可能多的“推送”代码

于 2012-10-30T15:24:51.627 回答
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>
于 2012-10-30T15:07:23.247 回答