[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

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 11:09:56 -0800 (PST)

Thanks Michael for the response however I am still having problems
getting this to work. I tweaked your code a bit to get it to work and
maybe through that process I broke something. 

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

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
Keywords