Pipelines that change attributes

Hi,

What's the right way of replacing the attributes on an element with 
others calculated based on those attributes?

I'm using a (XSLT-based) pipeline at the moment to convert some messy 
XHTML generated from WordML into a cleaner version that uses relative 
lengths and so on.[1] The first step is to transform the style 
attributes into css:* attributes where the name of each css:* attribute 
is the name of a CSS property and its value is the property value. The 
attributes you get should depend on the style attribute, so:

   <span style="font-family: Times; font-weight: bold">
     ...
   </span>

should become:

   <span css:font-family="Times" css:font-weight="bold">
     ...
   </span>

In other words, I want something like p:set-attributes, except that the 
new set of attributes needs to be calculated. This is an easily 
streamable operation, but I can't see any way to improve on my current 
augmented identity transform in XSLT. In particular, I can't use 
p:viewport because that would entail processing the entire subtree, 
rather than just the attributes, of the matched elements, which is no 
better than the pure XSLT approach.

Am I missing something?

If not, I propose adding an 'on' attribute to p:viewport that defaults 
to "subtree" but can also be set to "attrbutes". If the latter, the 
processor provides a document on the current port that contains an empty 
version of the element, with all its attributes. The result of the 
contained steps must be a single document; the attrbutes on its document 
element are used to replace the element's attributes in the result of 
the viewport. The descendants of the matched element *are* processed by 
the viewport.

For example,

<p:viewport on="attributes" match="*">
   <p:identity>
     <p:input port="source">
       <p:inline>
         <e processed="yes" />
       </p:inline>
     </p:input>
   </p:identity>
</p:viewport>

would replace all attrbutes on all elements in the viewport's source 
document with a 'processed' attribute with the value 'yes'. Note that 
the name of the result's document element is ignored.

This would meet my requirements both for expanding the style attribute 
into css:* attributes and for contracting the css:* attributes back into 
a style attribute at the end of my pipeline. For example

   <p:viewport on="attributes" match="*[@css:*]">
     <p:xslt>
       <p:input port="stylesheet">
         <p:inline>
           <e xsl:version="1.0">
             <xsl:attribute name="style">
               <xsl:for-each select="@css:*">
                 <xsl:value-of
                   select="concat(local-name(), ': ', ., '; ')" />
               </xsl:for-each>
             </xsl:attribute>
           </e>
         </p:inline>
       </p:input>
     </p:xslt>
   </p:viewport>

would create the necessary style attribute on my elements.

Cheers,

Jeni

[1] http://www.jenitennison.com/blog/node/3
-- 
Jeni Tennison
http://www.jenitennison.com

Received on Saturday, 5 May 2007 18:32:48 UTC