65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 XSL

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.95/5 (10投票s)

2014年6月6日

CPOL

9分钟阅读

viewsIcon

16492

downloadIcon

167

借助 XSL 进行转换

引言

XSL 转换快速、轻松,与任何其他服务器端或客户端方法相比,使用 XSL 转换文档类型变得毫不费力。因此,本文帮助您探索使用 XSL 可以实现多少功能。简而言之,创造力是 XSL 转换的唯一限制。

背景

我们经常需要将一个文档的内容转换为一种全新的文档类型,并具有不同的布局。例如,将博客文章提取出来作为新闻通讯发送。或者从 XML 文件的每个节点创建一个具有特定格式的文档。或者创建一个具有特定格式的 XML 文件,并将其更改为全新的格式。使用 XSL,我们可以做很多事情,而且它并不复杂。本文通过以下几点帮助您理解 XSL 转换:

  • 理解内容 - 标签、关键字
  • 实现简单转换
  • 选择性读取内容
  • 实现条件逻辑
  • 施加样式
  • 嵌入来自其他 XSL 资源的的代码

理解内容 - 标签、关键字等。

要开始 XSL 转换,我们首先需要创建一个 XSL 文件。首先,XSL 代表什么?嗯,它代表 EXtensible Stylesheet Language。因此,我们知道从技术上讲,XSL 文件是样式表,而且更多。现在,为了更好地理解,让我们继续在您的解决方案中添加一个 XSL 文件,使用 VS2012(这是我正在使用的)。当您打开它时,文件的内容如下所示(行号仅供参考,不会出现在实际代码中)。

1. <?xml version="1.0" encoding="utf-8"?>
2. <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3.    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
4.    <xsl:output method="xml" indent="yes"/>
5.
6.   <xsl:template match="@* | node()">
7.      <xsl:copy>
8.          <xsl:apply-templates select="@* | node()"/>
9.        </xsl:copy>
10.  </xsl:template>
11. </xsl:stylesheet>

在我们开始进行任何更改之前,让我们尝试理解每一行的含义。

  • 第 1 行 - 这指定 XSL 文档是 XML 版本 1.0 类型,并将使用 utf-8 类型的编码。可以根据您的要求更改编码。
  • 第 2 行 - 这一行标志着 XSL 文档的开始,我们看到它是一个样式表类型,并带有一些属性,这些属性是:
    • version 1.0,这是当前的默认值。
    • xsmlns: xsl - 将 XSL 的命名空间指定为默认命名空间。可以根据您的项目要求修改 xmlns:xsl 的值。
    • xmlns:msxsl - 这指定将使用的默认脚本语言。其他可能的值可以是 C#、VB、JScript、JavaScript、VisualBasic 或 CSharp。
    • exclude-result-prefixes - 这有助于避免在结果元素中出现命名空间声明,这些命名空间已在样式表中声明并使用。这有助于在路径表达式或匹配模式中仅选择节点,或用于插入扩展元素。
  • 第 4 行 - 指定转换后生成的文档将是 XML 类型,并且会进行缩进以便于阅读。这 xsl:output 的属性不止这两个。更详细的描述可以在 此处找到。
  • 第 6 行 - 指定匹配将发生在哪些元素上。当前值表示应匹配所有节点。如果我们想匹配整个 XML 文档,可以使用 "/" 代替。常见匹配模式的简要概述可以在 此处找到。
  • 第 7 行 - 此标签表示下一行中的选择将被复制并替换到此部分。
  • 第 8 行 - xsl:apply-template 标签确保仅处理通过 select 属性提供匹配值的元素。
  • 第 9 行 - 第 11 行 - 都是所有已打开标签的关闭标签。

所以,首先,我们现在知道 XSL 文件是什么样子,以及常用标签的含义和作用。

实现简单转换

下载 zip 文件Sample1 ,您会找到 2 个文件。一个是包含 CD 集合列表的 XML 文件,另一个是 XSL 文件,它将帮助我按照我想要的方式呈现 CD 集合。所以让我们看看 XSL 的内容。

 <xsl:template match="/">
    <html>
      <body>
        <h1>CD Collection</h1>
        <table border="1">
          <tr bgcolor="#9acd32">
            <th>Title</th>
            <th>Artist</th>
          </tr>
          <tr>
            <td>
              <xsl:value-of select="catalog/cd/title[text()='Red']"/>
            </td>
            <td>
              <xsl:value-of select="catalog/cd/artist[text()='The Communards']"/>
            </td>

          </tr>
        </table>
      </body>
    </html>
  </xsl:template>
  1. 模板匹配表示 XSL 应该与整个文档匹配。
  2. html 部分标志着转换后将创建的文档的开始。
  3. body 需要有一个标题,并且应该以表格形式列出 CD 集合。
  4. 有一个新的 xsl 标签称为 xsl:value-of。它返回所有与 select 属性中给出的条件匹配的文本。
  5. select 属性有一个 xpath 表达式。它表示匹配 cd 节点的子节点中值为“Red”的 title 节点,而 cd 节点又是 catalog 节点的子节点。

那么下一条表达式是什么意思?自己找出来。更改 XSL 文件并进行实验。但是要看到输出,您需要将 XML 文件与 XSL 相关联。那么如何做到呢?我知道 2 种方法:

  1. 打开 XML 文件,并在 xml 版本标签之后添加下面给出的行。
    <?xml-stylesheet type="text/xsl" href="CDCollection.xslt"?>

    在这里 href 应该映射到 XSL 文件的实际路径,如果它们在 2 个不同的位置。现在在 Internet Explorer 中打开 XML 并查看输出。

  2. 另一种方法是将这两个文件添加到 VS2010 或其他版本的解决方案中。添加一个项目并引用这些文件。在您需要调用转换代码的地方,首先引用下面给出的 2 个命名空间。
      • System.Xml
      • System.Xml.Xsl

像这样声明一个转换对象

XslTransform cdXslTransform = new XslTransform();

接下来使用 load 方法

cdXslTransform.Load("CdCollection.xslt");

然后调用转换方法

cdXslTransform.Transform("CdCollection.xml", "FormattedCdCollection.xml");

新文件将生成在与CdCollection.xml相同的位置。

所以,您有样本文件可以开始,也有转换技术可供选择。现在,开始尝试吧。

选择性读取内容

现在,一旦您根据您的要求调整了文件,其中一些更改可能有效,而另一些则无效。所以让我们理解各种 select 表达式。在我们实际讨论不同的表达式之前,让我们理解 XSL 中的表达式是纯粹的 xpath。所以,在这里,我们从表达式开始。

  • 您想显示硬编码文本 - 无需使用 select。直接将其写在您希望它出现的地方。就像我们为标题所做的那样。例如:
<h1>CD Collection</h1>
  • 您希望特定节点的文本出现,则执行以下操作:
    • <xsl:value-of> - 这只会写入节点的文本。
    • select 属性应将节点与特定值匹配。 title[text()='Red']
  • 您想复制匹配条件的整个元素 - 使用 <xsl:copy-of select="cd"/>
  • 您想选择父节点,其子节点匹配某个值 - select 的表达式将是 - <xsl:copy select="//cd[cd/title[text()='Red']"
  • 您想选择一个元素的值并在以后使用它 - <xsl:variable name="color" select="'red'" />。但您需要记住,与在其他编程语言中的变量不同,分配给变量的值不能被重新分配。
  • 您需要一个具有默认值的变量,该变量根据作用域具有不同的值 - 使用 <xsl:param>。与 <xsl:variable> 的语法相似,但有一个默认值并且可以被重新分配。
  • 您需要选择一个属性值匹配字符串的元素 - <xsl:value-of select="//cd[cd/title[@name='Red']",其中 name title 节点的属性。
  • 有很多您可能需要做的事情。已经内置了许多函数。可用的函数列表可以在 此处找到。

所以,现在您对该做什么以及如何继续试验有了更多的了解。

实现条件逻辑

现在,如果您一直在试验我们上面讨论的内容,您一定已经能够部分或全部地转换您的 XML。但 XSL 是另一种语言,我们总是希望使用一些条件逻辑。我们喜欢我们的 ifs 和 elses 以及 for-each while。那么我们可以在 XSL 中做同样的事情吗?让我们看看 XSL 中我们可以做什么。

  • 您想匹配单个条件或复制“if” - 使用 <xsl:if>。但不是 select 属性,我们需要 test 属性来匹配条件。所以语法是 - <xsl:if test="price &gt; 10">注意,因为 XSL 只是另一种 XML 文档,所以我们使用“&gt;”而不是通常的“>”符号,并使用“&lt;”代替“<”。
  • 您想使用 AND 或 OR 连接多个条件 - AND 和 OR 都可以用来连接条件,但只能是小写,即“and”和“or”。例如 - <xsl:if test="price &gt; 10 and price &lt; 20">
  • 您想实现 switch case 或 if-else if-else if -else - 使用 <xsl:choose>。语法将是
<xsl:choose>

        <xsl:when test="price &gt; 5">
          <td bgcolor="#ff00ff">
          <xsl:value-of select="artist"/></td>
        </xsl:when>
        <xsl:otherwise>
          <td><xsl:value-of select="artist"/></td>
        </xsl:otherwise>

</xsl:choose>
  • 您想实现 for-each - 使用 <xsl:for-each>,如下所示:
<xsl:for-each select="catalog/cd">
    <tr>
      <td><xsl:value-of select="title"/></td>
      <td><xsl:value-of select="artist"/></td>
    </tr>
    </xsl:for-each>

好了,现在您已经理解了条件逻辑和运算符。那么还在等什么?开始练习吧。只说一点,在您开始飞驰之前,请知道,与任何其他编程语言一样,在 XSL 中,您也可以将这些逻辑单独使用或与其他逻辑结合使用。

施加样式

所以在开始时,我们确实讨论过 XSL 是用于演示的。然后可以理解,我们希望用我们想要的样式来美化输出文档。那么我们可以在输出中使用样式吗?让我们尝试一些示例。

  • 您想为具有特定值的元素分配样式
<xsl:attribute name="style">

 <xsl:value-of select="'color: Red;'" />

</xsl:attribute>
  • 您想在 xsl 文件中声明一个 CSS 类。使用 <xsl:attribute-set/>. 您可以添加一个类,然后按照以下方式添加其定义:
<xsl:attribute-set name="quote">
    <xsl:attribute name="padding-start">2.5cm</xsl:attribute>
    <xsl:attribute name="line-height">11pt</xsl:attribute>
</xsl:attribute-set>

最好将所有属性集声明在顶部,以便整个文档都有其作用域。

  • 您想使用.css文件中声明的现有样式类 - 您可以通过引用它来在 XSL 文件中使用CdCollection.css,如下所示:
<link rel="stylesheet" type="text/css" href="CdCollection.css" />

只需将此行放在标题上方,您就会看到差异。尝试其他样式。要为 html 文档的正文添加样式。将下面的部分包含在.css文件中:

body{
}

所以也开始操作样式吧。

嵌入来自其他 XSL 资源的的代码

到目前为止,您将能够创建一个相当复杂的 XSL 文件来处理转换。但是仍然存在一个问题,我们是否需要为每次 XML 转换都创建一个 XSL 文件?如果我们为所有相似的文件集需要复制复杂的转换,难道不会很费力吗?嗯,别担心。编码世界并不那么糟糕。XSL 是可重用的,而且非常容易。那么我们如何做到呢?相当简单的方法是:

  • 您可以改用
    <xsl:import href="ResuableFormat.xsl"/>

import 标签引用外部资源,并将创建导入树。然后,您可以将导入的 XSL 所提供的任何功能用于您当前的 XSL 中。

  • 您也可以使用 <xsl:include>。它与 <xsl:import> 的区别在于 <xsl:include> 只能用作顶级元素。

所以,我们已经涵盖了 XSL 的大部分内容以及如何操作。希望这有所帮助。外面有很多资源。我只是试图将它们整合起来。我开始时引用的文章可以在 此处找到。示例 XML 和 XSL 是教程中可用示例的修改版本。另一个很棒的资源是 这个。请随时发表您的评论。

© . All rights reserved.