RE: [xsl] Problems with mixed content and inline elements when transforming XHTML into another XML format

Subject: RE: [xsl] Problems with mixed content and inline elements when transforming XHTML into another XML format
From: Tony Kinnis <kinnist@xxxxxxxxx>
Date: Thu, 23 Feb 2006 19:39:56 -0800 (PST)
Sorry to keep asking about this problem but I am still having issues.
The change you mention below does remove the error but now it never
hits the block of code to wrap the elements in the textnode. It is
simply outputting the input verbatim. Stepping through it in a debugger
it shows that it steps into the for-each-group statement then right
into the otherwise clause, outputs the entire document then it exits
processing as complete. It seems as though it is missing a statement in
the otherwise clause that causes it to recurse on the elements. I tried
a couple of different things with that but they were all wrong and
didn't produce the results I wanted.

See the previous message below for the input, stylesheet and desired
output because I think something is missing here or I am not asking my
question correctly. For convenience here is the entire stylesheet
including the change you suggested. Once again thanks for your help.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
version="2.0"
    xpath-default-namespace="http://www.w3.org/1999/xhtml";
    xmlns:f="http://whatever";
    xmlns:xs="http://www.w3.org/2001/XMLSchema";>
    
    <xsl:template match="/">
        <xsl:copy>
            <xsl:for-each-group select="node()"
group-adjacent="f:is-inline(.)">
                <xsl:choose>
                    <xsl:when test="current-grouping-key()">
                        <textnode><xsl:copy-of
select="current-group()"/></textnode>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:copy-of select="current-group()"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each-group>
        </xsl:copy>    
    </xsl:template>
    
    <xsl:function name="f:is-inline" as="xs:boolean">
        <xsl:param name="node" as="node()"/>
        <xsl:sequence select="$node instance of text() or
$node[self::u|self::b|self::i|self::strong|self::span|self::em|self::br]"/>
    </xsl:function>
</xsl:stylesheet>


--- Michael Kay <mike@xxxxxxxxxxxx> wrote:

> > 
> > I keep getting this error...
> > 
> > Description: A sequence of more than one item is not allowed as the
> > first argument of f:is-inline()
> > URL: http://www.w3.org/TR/xpath20/#ERRXPTY0004
> 
> Sorry, the code should have said group-adjacent="f:is-inline(.)"
> 
> Michael Kay
> http://www.saxonica.com/
> 
> > 
> > In case this this matters I am debugging this using the Oxygen
> editor
> > for the mac. The processor I have selected is Saxon8B. Once again
> help
> > is much appreciated.
> > 
> > To make this easier here is the full xsl doc, input I am testing
> and
> > desired output....
> > 
> > XSL document...
> > <?xml version="1.0" encoding="UTF-8"?>
> > <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
> > version="2.0"
> >     xpath-default-namespace="http://www.w3.org/1999/xhtml";
> >     xmlns:f="http://whatever";
> >     xmlns:xs="http://www.w3.org/2001/XMLSchema";>
> >     <xsl:template match="/">
> >         <xsl:copy>
> >             <xsl:for-each-group select="node()"
> >                 group-adjacent="f:is-inline(node())">
> >                 <xsl:choose>
> >                     <xsl:when test="current-grouping-key()">
> >                         <textnode><xsl:copy-of
> > select="current-group()"/></textnode>
> >                     </xsl:when>
> >                     <xsl:otherwise>
> >                         <xsl:copy-of select="current-group()"/>
> >                     </xsl:otherwise>
> >                 </xsl:choose>
> >             </xsl:for-each-group>
> >         </xsl:copy>    
> >     </xsl:template>
> >     
> >     <xsl:function name="f:is-inline" as="xs:boolean">
> >         <xsl:param name="node" as="node()"/>
> >         <xsl:sequence select="$node instance of text() or
> > $node[self::u|self::b|self::i|self::strong|self::span|self::em
> > |self::br]"/>
> >     </xsl:function>
> > </xsl:stylesheet>
> > 
> > XHTML Document...
> > 
> > <?xml version="1.0" encoding="utf-8"?>
> > <html xmlns="http://www.w3.org/1999/xhtml";>
> >     <head>
> >         <meta name="generator" content="HTML Tidy, see
> www.w3.org"/>
> >         <title>The Title Is</title>
> >     </head>
> >     <body>
> >         <ul id="bar">
> >             <li/>
> >             <li>foo<br/> after break <div/> after empty div</li>
> >             <li>bar<strong>baz</strong></li>
> >         </ul>
> >         <ol>
> >             <li>Item 1</li>
> >             <li>Item 2</li>
> >         </ol>
> >         <p><span>foo</span><br/> asdf <b>bold another</b>
> >             and <strong>a strong item</strong>
> >         </p>
> >         <div>
> >             Content of a <b>div tag</b> here.
> >             <ul>
> >                 <li>
> >                     Nested List Item 1
> >                 </li>
> >                 <li>
> >                     Nested List Item 2
> >                 </li>
> >             </ul>
> >             Now list is done
> >         </div>
> >     </body>
> > </html>
> > 
> > Desired output...
> > <?xml version="1.0" encoding="utf-8"?>
> > <html xmlns="http://www.w3.org/1999/xhtml";>
> >     <head>
> >         <meta name="generator" content="HTML Tidy, see
> www.w3.org"/>
> >         <title><textnode>The Title Is</textnode></title>
> >     </head>
> >     <body>
> >         <ul id="bar">
> >             <li/>
> >             <li><textnode>foo<br/> after break
> > </textnode><div/><textnode> after empty div</textnode></li>
> >             <li><textnode>bar<strong>baz</strong></textnode></li>
> >         </ul>
> >         <ol>
> >             <li><textnode>Item 1</textnode></li>
> >             <li><textnode>Item 2</textnode></li>
> >         </ol>
> >         <p><textnode><span>foo</span><br/> asdf <b>bold another</b>
> >             and <strong>a strong item</strong></textnode>
> >         </p>
> >         <div>
> >             <textnode>Content of a <b>div tag</b> here.</textnode>
> >             <ul>
> >                 <li>
> >                     <textnode>Nested List Item 1</textnode>
> >                 </li>
> >                 <li>
> >                     <textnode>Nested List Item 2</textnode>
> >                 </li>
> >             </ul>
> >             <textnode>Now list is done</textnode>
> >         </div>
> >     </body>
> > </html>
> > 
> > > -----Original Message-----
> > > You're using XSLT 2.0 so this can be solved using grouping
> > constructs.
> > > 
> > > Forget the templates that create <textnode> elements.
> > > 
> > > You want something like this, which causes adjacent 
> > "inline" nodes to
> > be
> > > grouped under a new element, with a function to decide 
> > whether a node
> > is an
> > > "inline" node:
> > > 
> > > <xsl:template match="div">
> > >   <xsl:copy>
> > >     <xsl:for-each-group select="node()"
> > > group-adjacent="f:is-inline(node())">
> > >       <xsl:choose>
> > >         <xsl:when test="current-grouping-key()">
> > >           <textnode><xsl:copy-of
> > select="current-group()"/></textnode>
> > >         </xsl:when>
> > >         <xsl:otherwise>
> > >           <xsl:copy-of select="current-group()"/>
> > >         </
> > >       </
> > >     </
> > >   </
> > > </
> > > 
> > > <xsl:function name="f:is-inline" as="xs:boolean">
> > >   <xsl:param name="node" as="node()"/>
> > >   <xsl:sequence select="$node instanceof text() or
> > > $node[self::u|self::b|self::i]"/>
> > > </xsl:function>
> > 
> > Michael Kay
> > http://www.saxonica.com/
> > 
> > __________________________________________________
> > Do You Yahoo!?
> > Tired of spam?  Yahoo! Mail has the best spam protection around 
> > http://mail.yahoo.com 
> 
> 


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 

Current Thread