xsl-list
[Top] [All Lists]

Re: inheritance and encapsulation in xslt? / xslt for xlink?

2003-07-22 01:17:37
Hi Howard,

Just to offer a couple of different approaches that you might
consider. You say:

The various .xsd files conform to the XBRL standard, which specifies
that XLink arcs are used to indicate which company-specific elements
correspond to which elements in the basic us-gaap-ci.xsd.
Specifically, the standard says that an arc element appears in the
company-specific .xsd to connect the general element to the more
specialized one, with an XLink "arcrole" attribute of
"http://www.xbrl.org/2003/role#general-special";. This specialization
process actually repeats many times. That is, the "general-special"
role is transative, and I want template behavior to default all the
way up the transitive chain of such roles.

What I would do, in this case, is to first break down the process into
two steps:

  company-specific  --(rename)-->  general  --(transform)-->  HTML

The (rename) step takes the company-specific elements and translates
them into the general elements to which they're related. For example,
acme_slushFundCash would be translated into ci_unrestrictedCash.

The (transform) step then takes the general elements and translates
them to HTML in the way that you're doing at the moment.

Since you have information about which element maps to which in the
XSD schemas, you can generate the stylesheet for the (rename) step
automatically rather than having to do it by hand. So this adds
another transformation into the process:

  company-specific  --(rename)-->  general  --(transform)-->  HTML
                          ^
                          |
                      (generate)
                          |
                          |
                       schemas

The stylesheet to do the (generate) step could be quite simple.
Something like:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
                xmlns="http://www.w3.org/1999/XSL/TransformAlias";>

<xsl:namespace-alias stylesheet-prefix="#default" result-prefix="xsl"/>

<xsl:template match="/">
  <stylesheet version="1.0">
    <xsl:apply-templates />
  </stylesheet>
</xsl:template>

<xsl:template 
match="definitionArc[(_at_)xlink:arcrole='http://www.xbrl.org/2003/role#general-specific']">
  <template match="{(_at_)xlink:to}">
    <xsl:element name="{(_at_)xlink:from}">
      <apply-templates />
    </xsl:element>
  </template>
</xsl:template>

</xsl:stylesheet>

If you wanted to provide non-default behaviour for some of the
elements, you would have to import this into a specialised stylesheet,
which instead copied through those elements that you wanted to
preserve, and have a specialised stylesheet for the HTML generation
for each company dialect.

Alternatively, you say:

The idea of IBM's DITA is to give just enough information in the
element definitions (.dtd's, but it could work for .xsd's) that the
automatically generated default .xsl files are unnecessary. Instead
of defining templates on the names of elements, you define them on
whether the element has a defaulted class attribute (from the .dtd)
that includes the name of the element or one of its ancestors in the
general-special chain. For example, the us-gaap-ci-2html.xsl might
really define a template like: <xsl:template
match="*[contains(@class,' ci_unrestrictedCash ']">cash is...

If you prefer, you could always get the (rename) step to annotate the
elements with class attributes rather than actually renaming the
elements. To generate the (rename) stylesheet, you'd use a (generate)
stylesheet like the one above but containing:

<xsl:template 
match="definitionArc[(_at_)xlink:arcrole='http://www.xbrl.org/2003/role#general-specific']">
  <template match="{(_at_)xlink:to}">
    <copy>
      <attribute name="class">
        <xsl:value-of select="@xlink:from" />
      </attribute>
      <apply-templates />
    </copy>
  </template>
</xsl:template>

---

XML Schema is designed to manage this kind of situation (specialised
elements used in place of general elements) using substitution groups.
If you were using substitution groups instead of this XLink mechanism,
then Schema-Aware XSLT 2.0 processors would be able to pick up on the
fact that the <acme_slushFundCash> is a member of the substitution
group <ci_unrestrictedCash>. You could then write templates like:

<xsl:template match="element(ci_unrestrictedCash)">
  ...
</xsl:template>

and this template would be used for every element that belonged to the
ci_unrestrictedCash substitution group. You could also have
specialised templates for the specialised elements, using template
priority or import priority to override these more general ones.

So this would tackle precisely the problem that you're encountering,
but it's very much something for the future, since:

  (a) you're not using substitution groups in your schema, from what I
      can tell
  (b) XSLT 2.0 isn't yet a standard
  (c) there aren't any (even experimental) Schema-Aware XSLT 2.0
      processors around that you could use

Cheers,

Jeni

---
Jeni Tennison
http://www.jenitennison.com/


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list