如何结合几个XSLT转换?

时间:2018-07-09 12:51:24

标签: xml xslt

我有一个HTML文件:

<!DOCTYPE html>
<html>
<head>
<title>A title of the article</title>
<style type="text/css">
body {
  font-family: Helvetica, arial, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  padding-top: 10px;
  padding-bottom: 10px;
  background-color: white;
  padding: 30px; }

body > *:first-child {
  margin-top: 0 !important; }
body > *:last-child {
  margin-bottom: 0 !important; }
</style>
</head>
<body>
  <p>The page is an article about an article.</p>
  <p>This paragraph is not very good paragraph</p>
  <p>This paragraph is very good paragraph</p>
  <h4 id="toc_0">Page content</h4>
  <ul>
    <li>An itroduction</li>
    <li>An inline piece of code <code>select * from dual</code></li>
    <li>Buttons <kbd>OK</kbd> and <kbd>Cancel</kbd></li>
  </ul>
  <div>
    <pre>
      <code class="language-none">select * from dual
      </code>
    </pre>
  </div>

  <h4 id="toc_1">Usage</h4>
  <table>
    <thead>
      <tr>
        <th>Page ID</th>
        <th>Page name</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1234</td>
        <td>Page number 1234</td>
      </tr>
      <tr> 
        <td>5678</td>
        <td>Page number 5678</td>
      </tr>
      <tr>
        <td>90AB</td>
        <td>Page number 90AB</td>
      </tr>
    </tbody>
  </table>
</body>
</html>

我需要执行以下操作:

  1. code替换标签kbdspan
  2. 为每个具有先前标记名称的新span添加一个类(即<code> ... </code>应该转换为<span class="code"> ... </span>,依此类推)
  3. 保留标签body的内容,并删除其余的内容。

我找到了部分制作方法。此转换执行步骤1和2:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

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

    <xsl:template match="kbd">
        <span class="kbd"><xsl:apply-templates select="@*|node()" /></span>
    </xsl:template>
</xsl:stylesheet>

此转换进入步骤3:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/html/body">
        <xsl:copy-of select="node()"/>
    </xsl:template>

    <xsl:template match="text()" />
</xsl:stylesheet>

但是每个转换只能完成其工作。我可以替换标签,也可以剪切body的内容。我尝试结合使用这些转换,但是失败了。
同样,第二个转换也不会添加类(如果已经存在的话)。例如,

<code class="language-none">

变成了这个

<span class="language-none">

虽然我想拥有以下内容(类名的顺序无关紧要):

<span class="language-none code">

有一件烦人的事情。当源文件包含

行时

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

然后我得到一个错误“无效的XML”。好的,我同意它是无效的,但是在第二次转换后,我的实用程序(在Mac上使用命令行实用程序xsltproc)将完全相同的行插入到结果文件中。

1 个答案:

答案 0 :(得分:1)

要结合这三个步骤,您可以为htmlbody编写仅处理子项的模板,为html/head不执行任何操作的模板,然后您需要找到某种添加方式新类并保留现有类,这是一个:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="html | html/body">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="html/head"/>

    <xsl:template match="code">
        <span class="{@class} code"><xsl:apply-templates select="@*[not(local-name() = 'class')] | node()" /></span>
    </xsl:template>

    <xsl:template match="kbd">
        <span class="{@class} kbd"><xsl:apply-templates select="@*[not(local-name() = 'class')] | node()" /></span>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bdxtqd