xsl-list
[Top] [All Lists]

[xsl] Managing cross references when combining XML files into one document

2006-12-29 07:51:08
Hi, I have a problem with multiple documents and a couple of approaches
whose feasibility I want to explore.

Background:

I have a library of XML documents, and a document schema which allows
documents to "include" other documents via an
  <include srcfile="uri" />
element. Each XML file is structured with a top-level <document> node.

The documents are edited using structured FrameMaker, which allows an XSL
process to run on the opened file before the user sees it (this process
performs a few Frame-required mods to the source, such as wrapping all
graphic elements in a paragraph-type element, and adjusting table
structures), and similarly another XSL process to run on the saved file
(this is the logical converse of the import XSL, obviously).

So far so good. At this point I have two XSL files which merge all the
"included" XML into one input file for Framemaker to edit, and split it all
apart again on save. Framemaker uses Xalan-C as its XSL engine, so we are
stuck with XSL 1.0 features, but this is sufficient (with Xalan's
<redirect:write> extension), and our files roundtrip.

The basic import XSL (without the Frame requirements) is this:
  <xsl:template match="/">
    <xsl:apply-templates>
      <xsl:with-param name="currdoc" select="" />
    </xsl:apply-templates>
  </xsl:template>

  <!-- Include content of subfiles (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>

Because the outer document name is unknown, the currdoc parameter is empty
unless the current node is inside at least one include level.

The requirement now is to handle cross-document references. These are noted
with a
  <link src="uri" | idref="id" />
element (where one or the other attribute is supplied, but not both). The
src attribute is used for external references, while the idref attribute is
used for internal references - this requirement is due to the way in which
Framemaker records cross-references.

I don't believe that the export side of this is going to be too difficult;
most links in the merged file will be internal (idref), and I can use this
idref to look up the id; that element's parent <include> gives me the target
file while the link's parent <include> gives me the source file; if they are
the same I retain the idref attribute, otherwise I replace it with the src
attribute. No problems there.

The difficulties lie on the import side. Here the lookup to the target id is
not possible because that id (probably) is not in the initial input file but
in one of the included documents. If I had control over the XSL steps I
could execute a second stylesheet to do a second pass after the document had
been fully expanded, but I can only invoke a single XSL step and I don't
know how to do two-stage processing, or even if it is possible. An
alternative option would be to treat all links as external (even when they
point to an internal element in the expanded file) but to do this I need to
know the document filename. Again, if I had control of the XSL steps I could
pass the name in a parameter, but I don't and I can't. Is there a smart way
of accessing the document name (it would become a Xalan-specific question at
this point)?

Thanks for any advice
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>
--~--