tags:

views:

675

answers:

3

Thank you all for the help ahead of time.

I am using XSL Templates to serve as web page templates for a web framework, the end output being XHTML 1.0 Strict; it takes xml input and outputs the XHTML. It works perfectly except for 1 problem - the end output is also outputting a xml node instead of just the contents. Here is the basic xml (missing some items, but the overall design is the same):

<Page>
  <PageScript>
    <Script>./js/myscript.js</Script>
  </PageScript>
  <PageCSS>
    <CSS>./css/mycss.css</CSS>
  </PageCSS>
  <PageContent>Blah blah blah</PageContent>
</Page>

Here is the XSL Template

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:response="http://www.ntforl.com/"
  xmlns="http://www.w3.org/1999/xhtml"
  xmlns:xhtml="http://www.w3.org/1999/xhtml"
  xmlns:lang="en">

  <xsl:output 
    method="xml" 
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" 
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" 
  />

  <xsl:template match="//PageCSS">
    <xsl:for-each select="CSS">
      <link type="text/css" rel="stylesheet">
        <xsl:attribute name="href">
          <xsl:value-of select="." />
        </xsl:attribute>
      </link>
    </xsl:for-each>
  </xsl:template>

  <xsl:template match="//PageScript">
    <xsl:for-each select="Script">
      <script type="text/javascript">
        <xsl:attribute name="src">
          <xsl:value-of select="." />
        </xsl:attribute>
      </script>
    </xsl:for-each>
  </xsl:template>


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

  <xsl:template match="/" disable-output-escaping="yes">
    <html>
      <head>
        <title>
          <xsl:value-of select="//PageTitle" />
        </title>
        <meta http-equiv="content-type" content="text/html;charset=utf-8" />
        <link type="text/css" rel="stylesheet" href="template/style/globalStyle.css" />
        <link type="text/css" rel="stylesheet" href="template/style/standards.css" />
        <xsl:apply-templates select="//PageCSS" />
        <script type="text/javascript" src="template/js/some_file.js"></script>
        <xsl:apply-templates select="//PageScript" />
      </head>
      <body onload="">
        <div id="container">
          <div id="top">
            <div class="clear" />
          </div>
          <div id="main">
            <div class="left" style="width: 708px; margin-top: 10px;">
              <h1 class="center">
                <xsl:value-of select="//PageTitle" />
              </h1>
            </div>
            <div class="clear" />
            <div id="rightPane">
              <div id="rightPaneContent">
                <xsl:apply-templates select="//PageContent" />
              </div>
              <img src="template/images/mainBgBottom.png" alt="" />
            </div>
          </div>
        </div>
      </body>
    </html>
  </xsl:template>
</xsl:stylesheet>

The Problem resides in the PageContent, and it only happens with the PageContent. When the transformation is run, the template outputs

<PageContent xmlns=""> node content </PageContent>

in the XHTML. I need to know how to get rid of it so I can have a valid XHTML 1.0 Strict document.

The weird thing is that the PageContent node is the only node to do this, no other node gets it content wrapped with the node name in the output. Any suggestions would be greatly appreciate. This is a late project that only has 1 or 2 problems left, and this is one of them.

+2  A: 

I would try replacing <xsl:apply-templates select="//PageContent" /> with:

<xsl:apply-templates select="//PageContent/node()" />
molf
+3  A: 

You call apply-templates on the PageContent node:

<xsl:apply-templates select="//PageContent" />

The only template that matches this is this one, so the PageContent node gets copied:

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

Probably you should add another template that matches PageContent and just processes the child nodes, without copying PageContent itself:

<xsl:template match="//PageContent">
  <xsl:apply-templates/>
</xsl:template>
sth
Thank you all, these are very helpful. I have one other question though. These get rid of the parent node problem, but the first node inside of the PageContent gets a `xlmns=""` attribute, and I was curious if that could be left of in any way.If this helps, the PageContent node holds xhtml - it is basically the main part of the page in xhtml - the result of running whatever process the user requested.
Robert DeBoer
+2  A: 

As already pointed out by @sth and @molf, you get the node copied by your identity template (<xsl:template match="@*|node()">), because no other template in your stylesheet matches <PageContent> nodes.

As an alternative to the solutions already presented by the other two, you could change the identity template to:

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

When <PageContent> is encountered now, the identity template does not match anymore. The implicit default template for elements will be used instead, which is:

<xsl:template match="*">
  <xsl:apply-templates />
</xsl:template>

This means that templates are going to be applied to <PageContent>'s children automagically, and the node itself is not going to be copied - just what you want.

Tomalak