简体   繁体   中英

How to transform already transformed XML using XSLT

I currently have the following structure in my 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. 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. (The template is going to add another node to "main-container"). I am using XSLT 3.0

Is it possible for me to transform XML twice, and if so, how do I do it?

Here's a simple (and very artificial) example:

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

<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; 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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