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: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Thu, 23 Feb 2006 23:51:29 -0000
> 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 

Current Thread