xsl-list
[Top] [All Lists]

[xsl] Output multiple files with different DTD or avoid the problem altogether?

2007-01-24 01:47:21
Hi

This is an XSL 1.0 question :-)

I may be on the wrong track here but would appreciate some guidance.

First I will explain the part of my stylesheet which is working. I am taking
an XML "super-document" which contains a top-level <document> element and
potentially lots of other sub-documents:

  <document>
    <title />
    ..
    <include src="uri-1">
      <document>
        <title />
        ..
        <include src="uri-2">
          <document>..etc..</document>
        </include>
        ..
      </document>
    </include>
    ..
    <include src="uri-n">
      <document>..</document>
    </include>
    ..
  </document>

and passing this document through a stylesheet which splits all the
subdocuments apart, so that the end-product is n+1 files (the outer skeleton
document and the n source files defined by the nested <include> elements.

For reasons that are probably obvious to anyone familiar with a popular
document editing application, I have to use Xalan as my XSL processor, and I
am making use of the <xalan:write> extension to output the subdocuments.

The relevant part of this XSL is here:

  <xsl:template match="/">  <!-- EXPORT -->
    <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="include">
    <xsl:variable name="file" select="@srcfile" />
    <xsl:element name="include">
      <xsl:attribute name="srcfile">
        <xsl:value-of select="$file" />
      </xsl:attribute>
    </xsl:element>
    <xalan:write select="$file">
      <xsl:apply-templates select="document" />
    </xalan:write>
  </xsl:template>

  <xsl:template match="document">
    <xsl:call-template name="sspi" />
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>

  <xsl:template name="sspi">
    <xsl:processing-instruction name="xml-stylesheet">
      <xsl:text>href="path_to_ss.xsl" type="text/xsl"</xsl:text>
    </xsl:processing-instruction>
  </xsl:template>

The individual <document> elements and their contents get written to the
files defined by the containing <include> elements, and the containing
<document> files retain an <include> element so that the super-document can
be put together again (by a different stylesheet).

The "sspi" template inserts the stylesheet processing instruction for each
XML document that is output, while the DOCTYPE is set as per the top-level

  <xsl:output doctype-system="path_to_dtd" method="xml" />

element included in my stylesheet.

OK, up to this point the whole deal is working well. The problem I am having
is with the stylesheet which stitches these files together again. The basis
of this import stylesheet is the following:

  <xsl:template match="/">  <!-- IMPORT -->
    <xsl:apply-templates>
      <xsl:with-param name="currdoc" />
    </xsl:apply-templates>
  </xsl:template>

<!-- Incl. subfiles in the result doc (inside an 'include' element -->
  <xsl:template match="include">
    <xsl:element name="include">
      <xsl:attribute name="srcfile">
        <xsl:value-of select="@srcfile" />
      </xsl:attribute>
      <xsl:apply-templates select="document(@srcfile)/document">
        <xsl:with-param name="currdoc" select="@srcfile" />
      </xsl:apply-templates>
    </xsl:element>
  </xsl:template>

  <xsl:template match="node()|@*">
    <xsl:param name="currdoc" />
    <xsl:copy>
      <xsl:apply-templates select="@*|node()">
        <xsl:with-param name="currdoc" select="$currdoc" />
      </xsl:apply-templates>
    </xsl:copy>
  </xsl:template>

It fulfils the job of merging the individual document files into one large
source file admirably, but a necessary refinement is bothering me.

Certain elements contain attributes which refer to external source file
names, and this import stylesheet needs to identify whether or not the
referenced source file is included (earlier or later) in the
"super-document" which it is creating. The method I thought I could use for
this was to maintain a separate lookup XML file which lists all included
document file names, in a flat structure (this is because, using Xalan, all
the techniques for multi-pass processing are unavailable to me, so I can't
pipeline the expanded file and post-process the references, nor can I create
a nodeset variable).

Fine, I can generate this lookup file separately, but that would mean the
user remembering to perform an additional step every time they changed the
structure. So I would like to generate this file in the same XSL process
that saves/exports the document. This means changing the root template (the
one labelled "EXPORT" above):

  <xsl:template match="/">
    <xsl:apply-templates />
    <xsl:if test="//include">
      <xalan:write select="'lookup.xml'">
        <xsl:element name="doctree">
          <xsl:for-each select="//include">
            <xsl:element name="include">
              <xsl:attribute name="srcfile">
                <xsl:value-of select="@srcfile" />
              </xsl:attribute>
            </xsl:element>
          </xsl:for-each>
        </xsl:element>
      </xalan:write>
    </xsl:if>
  </xsl:template>

Now when I save the super-document everything is created as required, EXCEPT
that the lookup XML file contains a reference to the same DTD as the
individual document files, i.e. it includes the line:

  <!DOCTYPE doctree SYSTEM "path_to_dtd">

instead of referring to a different DTD as befits the different content it
has. I'm not surprised, I haven't told it where the new DTD is - but I don't
know how. Somehow I need to override the top-level <xsl:output> element, but
there doesn't seem to be any way to do so.

After this lengthy saga (and many thanks for staying with me!) there are
thus two questions (and a reminder).

1. Is there a way define a different DTD for a particular output file?

2. Or is there a way to identify forward references to later included
subfiles without using a separate lookup table?

3. Reminder: this is Xalan and XSL 1.0 :-(

Cheers
Trevor


--~------------------------------------------------------------------
XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--

<Prev in Thread] Current Thread [Next in Thread>