[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

Re: XSLT 2.0 compability issue occured in topicmerge.X

Subject: Re: XSLT 2.0 compability issue occured in topicmerge.XSL in DITA 1.5.1
From: team wise <dfanster@xxxxxxxxx>
Date: Tue, 19 Jun 2012 17:25:59 +0800
Re:  XSLT 2.0 compability issue occured in topicmerge.X
Hi Michael,
Many thanks for your prompt response. You are right that XSLT 1.0
surpresses the error message or it is recoverable.

I have a favor to ask what kind of a running sample would be desirable
for you to spot the error.
I have tried replacing the line <xsl:variable
name="topicrefClass"><xsl:value-of select="@class"/></xsl:variable>
with this line <xsl:variable name="topicrefClass"
select="string(@class)"/> , but made no difference.

I grealty appeciate your time again.

2012/6/19, Michael Kay <mike@xxxxxxxxxxxx>:
>
>
> On 19/06/2012 07:25, team wise wrote:
>> Hi there,
>> When dealing with a XSL style sheet transition to XSLT 2.0, I just
>> encountered with this following error message:
>>
>>   [xslt]
>> D:\InfoShare\AppSOMC\Utilities\DITA-OT\SEMC_Infoshare\xsl\topicmerge.xsl:112:
>> Fatal Error! An attribute node (id) cannot be created after the
>> children of the containing element ( I just commented out line 112 and
>> subsequent lines).
>> [xslt]
>> D:\InfoShare\AppSOMC\Utilities\DITA-OT\SEMC_Infoshare\xsl\topicmerge.xsl:120:
>> Fatal Error! An attribute node (id) cannot be created after the
>> children of the containing element
> This is a "recoverable error" in XSLT 1.0: processors are allowed to
> recover by ignoring the attribute. But they aren't required to recover,
> they can also treat it as fatal. In XSLT 2.0 the WG decided to improve
> interoperability by making it a hard error, so all processors must
> report it.
>
> Despite trying to reconstitute your stylesheet with the original line
> numbers, I haven't been able to spot where the code is wrong. There
> should be a Saxon stack trace giving more detail of the call stack at
> the point of failure; alternatively running with -T will give you output
> that is voluminous but very informative. I'm happy to help debug it if
> you can provide a runnable sample.
>
> In general the fix is to make sure you always output the attributes of
> an element before outputting its child nodes.
>
> I noticed, incidentally, that the stylesheet is making liberal use of
> this kind of construct:
>
> <xsl:variable name="topicrefClass"><xsl:value-of
> select="@class"/></xsl:variable>
>
> when it should be doing
>
> <xsl:variable name="topicrefClass" select="string(@class)"/>
>
> Saxon does its best to optimize this, but it can only do so when it's
> possible to analyze all uses of the variable to ensure that the variable
> is always used as a string. When this isn't possible, you incur the high
> cost of constructing a temporary tree to hold the value, which is a very
> heavyweight data structure compared with a single string. I've seen
> stylesheets speeded up by a factor of 5 by fixing this problem.
>
> Michael Kay
> Saxonica
>>
>> There are a couple of threads over the Internet that are related to
>> the error ,  for example, Michael commented on a similar problem,
>> however, I am bitter at my wit ends to work out a solution that works
>> in this context.
>>
>> We implement Saxon 9. stylesheet is written in XSLT 1.0 as follows:
>>
>> <?xml version="1.0" encoding="UTF-8" ?>
>> <!-- This file is part of the DITA Open Toolkit project hosted on
>>       Sourceforge.net. See the accompanying license.txt file for
>>       applicable licenses.-->
>>
>> <!-- book.xsl
>>   | Merge DITA topics with "validation" of topic property
>>   *-->
>> <xsl:stylesheet version="1.0"
>> xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
>>
>> <!-- Include error message template -->
>> <xsl:import href="common/output-message.xsl"/>
>> <!-- Set the prefix for error message numbers -->
>> <xsl:variable name="msgprefix">DOTX</xsl:variable>
>>
>> <xsl:variable name="xml-path"></xsl:variable>
>>
>> <xsl:output method="xml" encoding="utf-8" />
>>
>> <xsl:template match="/*">
>>     <xsl:element name="{name()}">
>>       <xsl:apply-templates select="@*" mode="copy-element"/>
>>       <xsl:apply-templates select="*"/>
>>     </xsl:element>
>> </xsl:template>
>>
>> <xsl:template match="/*/*[contains(@class,' map/topicmeta ')]"
>> priority="1">
>>    <xsl:apply-templates select="." mode="copy-element"/>
>> </xsl:template>
>>
>> <xsl:template match="/*[contains(@class,' map/map
>> ')]/*[contains(@class,' topic/title ')]">
>>    <xsl:apply-templates select="." mode="copy-element"/>
>> </xsl:template>
>>
>> <xsl:template match="*[contains(@class,' map/topicmeta ')]"/>
>> <xsl:template match="*[contains(@class,' map/navref ')]"/>
>> <xsl:template match="*[contains(@class,' map/reltable ')]"/>
>> <xsl:template match="*[contains(@class,' map/anchor ')]"/>
>>
>> <xsl:template match="*[contains(@class,' map/topicref
>> ')][@href][not(@href='')][not(@print='no')]">
>>    <xsl:variable name="topicrefClass"><xsl:value-of
>> select="@class"/></xsl:variable>
>>    <xsl:comment>Start of imbed for<xsl:value-of
>> select="@href"/></xsl:comment>
>>    <xsl:choose>
>>      <xsl:when test="@format and not(@format='dita')">
>>         <!-- Topicref to non-dita files will be ingored in PDF
>> transformation -->
>>        <xsl:call-template name="output-message">
>>          <xsl:with-param name="msgnum">049</xsl:with-param>
>>          <xsl:with-param name="msgsev">I</xsl:with-param>
>>        </xsl:call-template>
>>      </xsl:when>
>>      <xsl:when test="contains(@href,'#')">
>>        <xsl:variable name="sourcefile"><xsl:value-of
>> select="substring-before(@href,'#')"/></xsl:variable>
>>        <xsl:variable name="sourcetopic"><xsl:value-of
>> select="substring-after(@href,'#')"/></xsl:variable>
>>        <xsl:variable name="targetName"><xsl:value-of
>> select="name(document($sourcefile,/)//*[@id=$sourcetopic][contains(@class,'
>> topic/topic ')][1])"/></xsl:variable>
>>        <xsl:if test="$targetName and not($targetName='')">
>>        <xsl:element name="{$targetName}">
>>          <xsl:apply-templates
>> select="document($sourcefile,/)//*[@id=$sourcetopic][contains(@class,'
>> topic/topic ')][1]/@*" mode="copy-element"/>
>>          <xsl:attribute name="refclass"><xsl:value-of
>> select="$topicrefClass"/></xsl:attribute>
>>          <xsl:apply-templates
>> select="document($sourcefile,/)//*[@id=$sourcetopic][contains(@class,'
>> topic/topic ')][1]/*" mode="copy-element">
>>            <xsl:with-param name="src-file"><xsl:value-of
>> select="$sourcefile"/></xsl:with-param>
>>          </xsl:apply-templates>
>>          <xsl:apply-templates/>
>>        </xsl:element>
>>        </xsl:if>
>>      </xsl:when>
>>      <!-- If the target is a topic, as opposed to a ditabase mixed file
>> -->
>>      <xsl:when test="document(@href,/)/*[contains(@class,' topic/topic
>> ')]">
>>        <xsl:variable name="targetName"><xsl:value-of
>> select="name(document(@href,/)/*)"/></xsl:variable>
>>        <xsl:if test="$targetName and not($targetName='')">
>>        <xsl:element name="{$targetName}">
>>          <xsl:apply-templates select="document(@href,/)/*/@*"
>> mode="copy-element"/>
>>          <xsl:attribute name="refclass"><xsl:value-of
>> select="$topicrefClass"/></xsl:attribute>
>>          <!-- If the root element of the topic does not contain an id
>> attribute, then generate one.
>>               Later, we will use these id attributes as anchors for PDF
>> bookmarks. -->
>>          <xsl:if test="not(document(@href,/)/*/@id)">
>>            <xsl:attribute name="id"><xsl:value-of
>> select="generate-id()"/></xsl:attribute>
>>          </xsl:if>
>>          <xsl:apply-templates select="document(@href,/)/*/*"
>> mode="copy-element">
>>            <xsl:with-param name="src-file"><xsl:value-of
>> select="@href"/></xsl:with-param>
>>          </xsl:apply-templates>
>>          <xsl:apply-templates/>
>>        </xsl:element>
>>        </xsl:if>
>>      </xsl:when>
>>      <!-- Otherwise: pointing to ditabase container; output each topic
>> in the ditabase file.
>>           The refclass value is copied to each of the main topics.
>>           If this topicref has children, they will be treated as
>> children of the<dita>  wrapper.
>>           This is the same as saving them as peers of the topics in the
>> ditabase file. -->
>>      <xsl:otherwise>
>>        <xsl:for-each select="document(@href,/)/*/*">
>>          <xsl:element name="{name()}">
>>            <xsl:apply-templates select="@*" mode="copy-element"/>
>>            <xsl:attribute name="refclass"><xsl:value-of
>> select="$topicrefClass"/></xsl:attribute>
>>            <xsl:apply-templates select="*" mode="copy-element"/>
>>          </xsl:element>
>>        </xsl:for-each>
>>        <xsl:apply-templates/>
>>      </xsl:otherwise>
>>    </xsl:choose>
>> </xsl:template>
>>
>> <xsl:template match="*[contains(@class,' map/topicref ')][not(@href)]">
>>    <xsl:element name="{name()}">
>>      <xsl:apply-templates select="@*" mode="copy-element"/>
>>      <xsl:apply-templates/>
>>    </xsl:element>
>> </xsl:template>
>>
>> <!--xsl:template
>> match="*|@*|comment()|processing-instruction()|text()"
>> mode="copy-element">
>> <xsl:param name="src-file"></xsl:param>
>>    <xsl:copy>
>>      <xsl:apply-templates
>> select="*|@*|comment()|processing-instruction()|text()"
>> mode="copy-element">
>>        <xsl:with-param name="src-file"><xsl:value-of
>> select="$src-file"/></xsl:with-param>
>>      </xsl:apply-templates>
>>    </xsl:copy>
>> </xsl:template-->
>>
>>    <xsl:template match="@id" mode="copy-element">
>>      <xsl:attribute name="id"><xsl:value-of
>> select="generate-id(.)"/></xsl:attribute>
>>    </xsl:template>
>>
>> <xsl:template match="@href" mode="copy-element" priority="1">
>>    <xsl:param name="src-file"></xsl:param>
>>
>>    <xsl:variable name="file-path">
>>      <xsl:call-template name="get-file-path">
>>        <xsl:with-param name="src-file">
>>          <xsl:value-of select="$src-file"/>
>>        </xsl:with-param>
>>      </xsl:call-template>
>>      <xsl:value-of select="."/>
>>    </xsl:variable>
>>
>>    <xsl:variable name="file-path-new">
>>      <xsl:call-template name="normalize-path">
>>        <xsl:with-param name="file-path">
>>          <xsl:value-of select="translate($file-path,'\','/')"/>
>>        </xsl:with-param>
>>      </xsl:call-template>
>>    </xsl:variable>
>>
>>    <xsl:choose>
>>      <xsl:when test="contains(.,'://') or ../@scope='external' or
>> ../@scope='peer'">
>>        <xsl:copy/>
>>      </xsl:when>
>>      <xsl:when test="(parent::*[contains(@class,' topic/xref ')] or
>> parent::*[contains(@class,' topic/link ')]) and (not(../@format) or
>> ../@format='dita' or ../@format='DITA')">
>>        <xsl:choose>
>>          <xsl:when test="starts-with(.,'#')">
>>            <xsl:variable name="refer-path"
>> select="substring-after(.,'#')"/>
>>            <xsl:choose>
>>              <xsl:when test="contains($refer-path,'/')">
>>                <xsl:variable name="topic-id"
>> select="substring-before($refer-path,'/')"/>
>>                <xsl:variable name="target-id"
>> select="substring-after($refer-path,'/')"/>
>>                <xsl:variable name="href-value">
>>                  <xsl:value-of
>> select="generate-id(//*[contains(@class,' topic/topic
>> ')][@id=$topic-id]//*[@id=$target-id]/@id)"/>
>>                </xsl:variable>
>>                <xsl:if test="not($href-value='')">
>>                  <xsl:attribute
>> name="href"><xsl:text>#</xsl:text><xsl:value-of
>> select="$href-value"/></xsl:attribute>
>>                </xsl:if>
>>              </xsl:when>
>>              <xsl:otherwise>
>>                <xsl:variable name="href-value">
>>                  <xsl:value-of
>> select="generate-id(//*[contains(@class,' topic/topic
>> ')][@id=$refer-path]/@id)"/>
>>                </xsl:variable>
>>                <xsl:if test="not($href-value='')">
>>                  <xsl:attribute
>> name="href"><xsl:text>#</xsl:text><xsl:value-of
>> select="$href-value"/></xsl:attribute>
>>                </xsl:if>
>>              </xsl:otherwise>
>>            </xsl:choose>
>>          </xsl:when>
>>          <xsl:when test="contains(.,'#')">
>>            <xsl:variable name="file-name"
>> select="substring-before(.,'#')"/>
>>            <xsl:variable name="refer-path"
>> select="substring-after(.,'#')"/>
>>            <xsl:variable name="file-name-doc"
>> select="document($file-name,/)"/>
>>            <xsl:if test="$file-name-doc and not($file-name-doc='')">
>>            <xsl:choose>
>>              <xsl:when test="contains($refer-path,'/')">
>>                <xsl:variable name="topic-id"
>> select="substring-before($refer-path,'/')"/>
>>                <xsl:variable name="target-id"
>> select="substring-after($refer-path,'/')"/>
>>                <xsl:variable name="href-value">
>>                  <xsl:value-of
>> select="generate-id($file-name-doc//*[contains(@class,' topic/topic
>> ')][@id=$topic-id]//*[@id=$target-id]/@id)"/>
>>                </xsl:variable>
>>                <xsl:if test="not($href-value='')">
>>                  <xsl:attribute
>> name="href"><xsl:text>#</xsl:text><xsl:value-of
>> select="$href-value"/></xsl:attribute>
>>                </xsl:if>
>>              </xsl:when>
>>              <xsl:otherwise>
>>                <xsl:variable name="href-value">
>>                  <xsl:value-of
>> select="generate-id($file-name-doc//*[contains(@class,' topic/topic
>> ')][@id=$refer-path]/@id)"/>
>>                </xsl:variable>
>>                <xsl:if test="not($href-value='')">
>>                  <xsl:attribute
>> name="href"><xsl:text>#</xsl:text><xsl:value-of
>> select="$href-value"/></xsl:attribute>
>>                </xsl:if>
>>              </xsl:otherwise>
>>            </xsl:choose>
>>            </xsl:if>
>>          </xsl:when>
>>          <xsl:otherwise>
>>            <xsl:variable name="current-doc" select="document(.,/)"/>
>>            <xsl:if test="$current-doc and not($current-doc='')">
>>            <xsl:choose>
>>              <xsl:when test="$current-doc//*[contains(@class,'
>> topic/topic ')]/@id">
>>                <xsl:attribute
>> name="href"><xsl:text>#</xsl:text><xsl:value-of
>> select="generate-id($current-doc//*[contains(@class,' topic/topic
>> ')][1]/@id)"/></xsl:attribute>
>>              </xsl:when>
>>              <xsl:otherwise><xsl:text>#</xsl:text><xsl:value-of
>> select="generate-id($current-doc//*[contains(@class,' topic/topic
>> ')][1])"/></xsl:otherwise>
>>            </xsl:choose>
>>            </xsl:if>
>>          </xsl:otherwise>
>>        </xsl:choose>
>>
>>      </xsl:when>
>>      <xsl:otherwise>
>>        <xsl:attribute name="href">
>>          <xsl:value-of select="$file-path-new"/>
>>        </xsl:attribute>
>>      </xsl:otherwise>
>>    </xsl:choose>
>> </xsl:template>
>>
>> <xsl:template name="get-file-path">
>>    <xsl:param name="src-file"/>
>>    <xsl:if test="contains($src-file,'/')">
>>      <xsl:value-of select="substring-before($src-file,'/')"/>
>>      <xsl:text>/</xsl:text>
>>      <xsl:call-template name="get-file-path">
>>        <xsl:with-param name="src-file">
>>          <xsl:value-of select="substring-after($src-file,'/')"/>
>>        </xsl:with-param>
>>      </xsl:call-template>
>>    </xsl:if>
>> </xsl:template>
>>
>> <xsl:template name="normalize-path">
>>          <xsl:param name="file-path" />
>>          <xsl:choose>
>>              <xsl:when test="contains($file-path,'..')">
>>                  <xsl:variable name="firstdir"
>> select="substring-before($file-path, '/')" />
>>                  <xsl:variable name="newpath"
>> select="substring-after($file-path,'/')" />
>>                  <xsl:choose>
>>                      <xsl:when test="$firstdir='..'">
>>                          <xsl:text>../</xsl:text>
>>                          <xsl:call-template name="normalize-path">
>>                              <xsl:with-param name="file-path">
>>                                  <xsl:value-of select="$newpath"/>
>>                              </xsl:with-param>
>>                          </xsl:call-template>
>>                      </xsl:when>
>>                      <xsl:otherwise>
>>                          <xsl:variable name="beforedotdot"
>> select="substring-before($file-path,'/..')"></xsl:variable>
>>                          <xsl:variable name="beforedotdotparent">
>>                              <xsl:call-template name="parent-path">
>>                                  <xsl:with-param name="pathname"
>> select="$beforedotdot" />
>>                              </xsl:call-template>
>>                          </xsl:variable>
>>                          <xsl:variable name="afterdotdot"
>> select="substring-after($file-path,'../')"></xsl:variable>
>>                          <xsl:call-template name="normalize-path">
>>                              <xsl:with-param name="file-path">
>>                                  <xsl:value-of
>> select="concat($beforedotdotparent,$afterdotdot)"/>
>>                              </xsl:with-param>
>>                          </xsl:call-template>
>>                      </xsl:otherwise>
>>                   </xsl:choose>
>>              </xsl:when>
>>              <xsl:otherwise>
>>                  <xsl:value-of select="$file-path"></xsl:value-of>
>>              </xsl:otherwise>
>>          </xsl:choose>
>>   </xsl:template>
>> 	
>> 	<xsl:template name="parent-path">
>>          <xsl:param name="pathname" />
>>          <xsl:choose>
>>              <xsl:when test="contains($pathname, '/')">
>>                  <xsl:value-of select="substring-before($pathname,
>> '/')"/>
>>                  <xsl:text>/</xsl:text>
>>                  <xsl:call-template name="parent-path">
>>                      <xsl:with-param name="pathname"
>> select="substring-after($pathname,'/')"/>
>>                  </xsl:call-template>
>>              </xsl:when>
>>          </xsl:choose>
>>      </xsl:template>
>>
>>    <xsl:template match="processing-instruction()">
>>      <xsl:copy></xsl:copy>
>>    </xsl:template>
>>
>> </xsl:stylesheet>
>>
>> Are there anyone out there who had similar experience before? How did
>> you manage to overcome it?
>>
>> Thank you in advance
>> Ray
>
>


-- 
Keep an Exacting Eye for Detail

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.