Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty/blank namespace declarations being generated within result-document

I have written a package for converting XMLs to ePubs. Everything works fine, except some cases, where blank namespace (xmlns="") nodes are being written to the result-documents. Prior to transformation, I prepared temporary variables for holding main-segments(i.e., meta, body etc.) and finally copied the nodes(using xsl:copy-of[@copy-namespaces='no'] instruction) to result-document. I also have used @exclude-result-prefixes='ns_list_sep_by_space' within xsl:transform element and still not able to get desired result.

oXygen IDE shows a message in pop-up saying:

When using xsl:copy-of the new elements will also have namespace nodes copied from the original element node, unless they are excluded by specifying copy-namespaces="no". If this attribute is omitted, or takes the value yes, then all the namespace nodes of the original element are copied to the new element. If it takes the value no, then none of the namespace nodes are copied: however, namespace nodes will still be created in the result tree as required by the namespace fixup process.


Here is some more details of my problem:

Main stylesheet:
main.xsl:main caller

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
    xmlns:cylian="local-ns-for-extension-functions"
    exclude-result-prefixes="xs xd cylian"
    version="2.0">

    <xsl:import href="modules/core.xsl"/>

    <xsl:variable name="base" select="base-uri()" as="xs:anyURI"/>

    <xsl:template match="/">
        <xsl:call-template name="procA"/>
    </xsl:template>

</xsl:transform>

Main stylesheet:
core.xsl: core processing unit

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
        xmlns:cylian="local-ns-for-extension-functions"
        exclude-result-prefixes="xs xd cylian"
        version="2.0">

      <xsl:import href="sub1.xsl"/>  
      <xsl:import href="sub2.xsl"/>  
      <!--and more-->  

      <!-- variable to hold intermediate results for stage1 -->
      <xsl:variable name="stage1">
          <cylianz>
              <xsl:copy-of select="$a" copy-namespaces="no"/>
              <xsl:copy-of select="$b" copy-namespaces="no"/>
              <!--and more-->
          </cylianz>
      </xsl:variable>

      <!-- variable to hold intermediate results for stage2 -->
      <xsl:variable name="stage2">
          <cylianz>
            <xsl:for-each select="$stage1//cylian">
                <xsl:sort select="@pos"/>
                <xsl:sequence select="."/>
            </xsl:for-each>
          </cylianz>
      </xsl:variable>
      <xsl:template name="procA">
          <xsl:for-each select="$stage2//cylian">
              <xsl:result-document href="{concat($outdir,@href)}" format="general">
                  <xsl:call-template name="procB">
                        <xsl:with-param name="context" select="."/>
                        <xsl:with-param name="title">
                            <xsl:value-of select="$book_title"/>
                        </xsl:with-param>
                   </xsl:call-template>
              </xsl:result-document>
          </xsl:for-each>
      </xsl:template>
     <xsl:template name="procB">
         <xsl:param name="context"/>
         <xsl:param name="title"/>
         <html xmlns="http://www.w3.org/1999/xhtml">
         <head>
              <xsl:call-template name="header">
                  <xsl:with-param name="title" select="$title"/>
               </xsl:call-template>
         </head>
         <body>
              <div id="root">
                  <xsl:apply-templates select="."/>
              </div>
         </body>
    </html>
</xsl:template>

<!--
 1/ other rules are shortened for clarity
 2/ declaration «xmlns:cylian='local-ns-for-extension-functions'» has to retain, some parts of transformation uses some extension functions from that namespace
-->

</xsl:transform>

and here's the output: a.html

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
  PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
   <head>
      <meta xmlns="" http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
      <title xmlns="">BookTitle</title>
          <!--
              2012.04.16 - 18:27:36 [XSLT processor: SAXON 9.1.0.5 from Saxonica]
          -->
      <link xmlns="" href="isbn.css" type="text/css" rel="stylesheet"/>
   </head>
   <body>
      <div id="root">
         <div xmlns="" id="a1">
            <!--...-->
         </div>
      </div>
   </body>
</html>

I hope it would be easier to understand what's the problem is going on. All suggestions are welcome. Thanks in advance.

like image 871
Cylian Avatar asked Dec 21 '22 23:12

Cylian


2 Answers

Well we need to see your code to be sure but I suspect you have e.g.

<xsl:template match="/">
  <foo xmlns="http://example.com/ns">
    <xsl:apply-templates/>
  </foo>
</xsl:template>

<xsl:template match="whatever">
  <bar/>
</xsl:template>

and then you get

<foo xmlns="http://example.com/ns">
  <bar xmlns=""/>
</foo>

while you want

<foo xmlns="http://example.com/ns">
  <bar/>
</foo>

To fix that make sure you move the default namespace declaration on the xsl:stylesheet element with e.g.

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="http://example.com/ns">
  version="1.0">

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

    <xsl:template match="whatever">
      <bar/>
    </xsl:template>

</xsl:stylesheet>

that way it applies to all result elements created in different templates.

[edit] Based on the samples you have provided now I think my suggestion is right, only with several files you need to make sure that all stylesheet modules you have put xmlns="http://www.w3.org/1999/xhtml" on the xsl:stylesheet respectively xsl:transform elements so that all result elements end up in the XHTML namespace.

[second edit] I think you want

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns="http://www.w3.org/1999/xhtml"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
        xmlns:cylian="local-ns-for-extension-functions"
        exclude-result-prefixes="xs xd cylian"
        version="2.0">

      <xsl:import href="sub1.xsl"/>  
      <xsl:import href="sub2.xsl"/>  
      <!--and more-->  

      <!-- variable to hold intermediate results for stage1 -->
      <xsl:variable name="stage1" xmlns="">
          <cylianz>
              <xsl:copy-of select="$a" copy-namespaces="no"/>
              <xsl:copy-of select="$b" copy-namespaces="no"/>
              <!--and more-->
          </cylianz>
      </xsl:variable>

      <!-- variable to hold intermediate results for stage2 -->
      <xsl:variable name="stage2" xmlns="">
          <cylianz>
            <xsl:for-each select="$stage1//cylian">
                <xsl:sort select="@pos"/>
                <xsl:sequence select="."/>
            </xsl:for-each>
          </cylianz>
      </xsl:variable>
      <xsl:template name="procA">
          <xsl:for-each select="$stage2//cylian">
              <xsl:result-document href="{concat($outdir,@href)}" format="general">
                  <xsl:call-template name="procB">
                        <xsl:with-param name="context" select="."/>
                        <xsl:with-param name="title">
                            <xsl:value-of select="$book_title"/>
                        </xsl:with-param>
                   </xsl:call-template>
              </xsl:result-document>
          </xsl:for-each>
      </xsl:template>
     <xsl:template name="procB">
         <xsl:param name="context"/>
         <xsl:param name="title"/>
         <html >
         <head>
              <xsl:call-template name="header">
                  <xsl:with-param name="title" select="$title"/>
               </xsl:call-template>
         </head>
         <body>
              <div id="root">
                  <xsl:apply-templates select="."/>
              </div>
         </body>
    </html>
</xsl:template>


</xsl:transform>

And then if you have any additional modules supposed to produce XHTML elements make sure you put xmlns="http://www.w3.org/1999/xhtml" on the root element of the module or if you need to create elements in other namespaces as well then on any template supposed to output XHTML.

like image 147
Martin Honnen Avatar answered Apr 27 '23 17:04

Martin Honnen


There are two kinds of "unwanted" namespace declarations that might appear in your output: declarations that are unwanted because they are redundant noise (they declare namespace prefixes that aren't used), and declarations that are unwanted because they put the elements in a different namespace from the one intended.

In the first case, XSLT provides features such as exclude-result-prefixes and copy-namespaces='no' to get rid of the noise.

In the second case (which is where I think you are), the namespace declarations are a symptom of the fact that the stylesheet author created the elements in the wrong namespace in the first place, and the solution is to look at the code that created the elements, and fix it. For example you might have written a literal result element <foo> that creates an element in no namespace, when you intended <foo xmlns="something"/> to create it in some other namespace.

like image 44
Michael Kay Avatar answered Apr 27 '23 15:04

Michael Kay