简体   繁体   English

如何使用XSLT转换已转换的XML

[英]How to transform already transformed XML using XSLT

I currently have the following structure in my XSLT: 我的XSLT当前具有以下结构:

<xsl:template match="/" xml:space="preserve">
    <html>
        <head>
            <!--stuff here -->
        </head>
        <body>
            <!--stuff here -->
            <xsl:call-template name="page-content" />
            <!--stuff here -->
        </body>
    </html>
</xsl:template>

The above file is being imported by other XSLT files, which implement the page-content template. 上面的文件正在由其他XSLT文件导入,这些文件实现了page-content模板。 Here's a sample page-content template: 这是示例页面内容模板:

<xsl:template name="page-content">
<div class="main-container">
    <div class="row">
         <xsl:apply-templates select="data/document/content/node()" mode="copy" />
    </div>
</div>
</xsl:template>

I want to take the transformed XML returned by page-content , and match another template to it. 我想获取page-content返回的转换后的XML,并将另一个模板与其匹配。 (The template is going to add another node to "main-container"). (模板将向“ main-container”添加另一个节点)。 I am using XSLT 3.0 我正在使用XSLT 3.0

Is it possible for me to transform XML twice, and if so, how do I do it? 我是否可以两次转换XML,如果可以,我该怎么做?

Here's a simple (and very artificial) example: 这是一个简单的(非常人为的)示例:

XML XML

<lines>
    <line id="1"/>
    <line id="2"/>
    <line id="3"/>
    <line id="4"/>
    <line id="5"/>
    <line id="6"/>
    <line id="7"/>
    <line id="8"/>
    <line id="9"/>
    <line id="10"/>
    <line id="11"/>
    <line id="12"/>
    <line id="13"/>
    <line id="14"/>
    <line id="15"/>
    <line id="16"/>
    <line id="17"/>
    <line id="18"/>
    <line id="19"/>
    <line id="20"/>
    <line id="21"/>
    <line id="22"/>
    <line id="23"/>
    <line id="24"/>
    <line id="25"/>
</lines>

XSLT 2.0 XSLT 2.0

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

<xsl:template match="/lines">
    <!-- first-pass -->
    <xsl:variable name="pages">
        <xsl:call-template name="paginate">
            <xsl:with-param name="lines" select="line"/>
        </xsl:call-template>
    </xsl:variable>
    <!-- output -->
    <output>
        <xsl:apply-templates select="$pages"/>
    </output>
</xsl:template>

<xsl:template match="page">
    <xsl:copy>
        <xsl:attribute name="number">
            <xsl:number/>
        </xsl:attribute>
        <xsl:copy-of select="line"/>
    </xsl:copy>
</xsl:template>

<xsl:template name="paginate">
    <xsl:param name="lines"/>
    <xsl:param name="pagesize" select="10"/>
    <page>
        <xsl:copy-of select="$lines[position() le $pagesize]"/>
    </page>
    <xsl:if test="count($lines) gt $pagesize">
        <xsl:call-template name="paginate">
            <xsl:with-param name="lines" select="$lines[position() gt $pagesize]"/>
        </xsl:call-template>
    </xsl:if>
</xsl:template>

</xsl:stylesheet>

Result 结果

<?xml version="1.0" encoding="UTF-8"?>
<output>
   <page number="1">
      <line id="1"/>
      <line id="2"/>
      <line id="3"/>
      <line id="4"/>
      <line id="5"/>
      <line id="6"/>
      <line id="7"/>
      <line id="8"/>
      <line id="9"/>
      <line id="10"/>
   </page>
   <page number="2">
      <line id="11"/>
      <line id="12"/>
      <line id="13"/>
      <line id="14"/>
      <line id="15"/>
      <line id="16"/>
      <line id="17"/>
      <line id="18"/>
      <line id="19"/>
      <line id="20"/>
   </page>
   <page number="3">
      <line id="21"/>
      <line id="22"/>
      <line id="23"/>
      <line id="24"/>
      <line id="25"/>
   </page>
</output>

The first pass divides the lines into groups of 10; 第一遍将线分为10组; then the second pass processes the groups. 然后第二遍处理组。

You're thinking on the right lines: pipelines of simple transformations are the right way to implement a complex transformation, especially when it allows you to reuse the components of the pipeline. 您正在考虑正确的路线:简单转换的管道是实现复杂转换的正确方法,尤其是当它允许您重用管道的组件时。 Because a stylesheet is essentially a function (the output is a function of the input), pipelining is equivalent to functional composition (applying one function to the result of another). 因为样式表本质上是一个函数(输出是输入的函数),所以流水线等效于功能组合(将一个函数应用于另一个函数的结果)。

There are two ways of organizing a pipeline of transformations, "single-stylesheet" and "multiple-stylesheet". 有两种组织转换管道的方式,“单个样式表”和“多个样式表”。 In the first case, as here, you capture the result of applying templates into a temporary tree held in a variable, and then you apply-templates to that variable, often in a different mode (to make sure that template rules apply only to one phase of processing). 在第一种情况下,如此处所示,您捕获了将模板应用于变量中包含的临时树的结果,然后将模板应用于该变量,通常采用不同的模式(以确保模板规则仅适用于一个处理阶段)。 In the second case, you write separate stylesheets, and apply one to the output of another, using another language (Java, Ant, XProc, shell-script) to do the coordination. 在第二种情况下,您编写单独的样式表,然后使用另一种语言(Java,Ant,XProc,shell脚本)将样式表应用于另一个样式表的输出。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM