Question

I'm a newcomer to XSLT, XSL and XML manipulation techniques. Right now i do some simple transformations to this example XML:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="main.xsl"?>
<content base-url="../../../">
    <article title="TITLE_HERE" timestamp="TIME_HERE">
        <p>SOME TEXT HERE <a href="URL.xml">LINKTEXT</a>.</p>
    </article>
</content>

Applying this 'main.xsl' transformation:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns="http://www.w3.org/1999/xhtml">

<xsl:output method="xml"
            version="1.0"
            encoding="UTF-8"
            doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
            doctype-public="-//W3C//DTD XHTML 1.1//EN"
            indent="yes"/>

<xsl:strip-space elements="*"/>

<xsl:param  name="base"
            select="/content/@base-url"/>

<!-- PAGE TEMPLATE -->
<xsl:template match="/content">
    <html lang="en">
        <head>
           ...
        </head>
        <body>
            <div class="content">
                <xsl:apply-templates match="article"/>
            </div>
        </body>
    </html>
</xsl:template>

<!-- ARTICLE NODE TEMPLATE -->
<xsl:template match="article">
    <h2>
        <xsl:value-of select="@title"/>
    </h2>
    <h3>
        <xsl:value-of select="@timestamp"/>
    </h3>
    <xsl:copy-of select="."/>
</xsl:template>

</xsl:stylesheet>

As you can see, copy-of is used. Problem is with anchor link. When using copy-of, i cannot use concat function, as was using within template:

<xsl:template match="a">
    <a href="{concat($base, @href)}">
        <xsl:value-of select="."/>
    </a>
</xsl:template>

So, basically, there is need to use some recursion that will output whole nodes (tags and attributes) but without childs (text and other), recursively parsing them with assigned templates.

How can this be done?

Was it helpful?

Solution

You can use the following XSLT: new template that matches "node() | @*" copies the the nodes and attributes as it is. And instead of copy-of I've used apply-templates:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
            xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns="http://www.w3.org/1999/xhtml">

<xsl:output method="xml"
        version="1.0"
        encoding="UTF-8"
        doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
        doctype-public="-//W3C//DTD XHTML 1.1//EN"
        indent="yes"/>

<xsl:strip-space elements="*"/>

<xsl:param  name="base"
        select="/content/@base-url"/>

<!-- PAGE TEMPLATE -->
<xsl:template match="/content">
    <html lang="en">
        <head>
       ...
        </head>
        <body>
            <div class="content">
                <xsl:apply-templates select="article"/>
            </div>
        </body>
    </html>
</xsl:template>

<xsl:template match="a">
    <a href="{concat($base, @href)}">
        <xsl:value-of select="."/>
    </a>
</xsl:template>

<!-- ARTICLE NODE TEMPLATE -->
<xsl:template match="article">
    <h2>
        <xsl:value-of select="@title"/>
    </h2>
    <h3>
        <xsl:value-of select="@timestamp"/>
    </h3>
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="node() | @*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top