Solved

Help with an XSLT transformation that is not working.

Posted on 2006-12-01
10
343 Views
Last Modified: 2008-02-20
Help with an XSLT transformation that is not working.

I need help fixing this transformation... it does not seem to work completely.

Here is the XML:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="skins/default/ajax.xslt"?>
<ajax>
      <block>
            <text>
                  random number -&gt; 760<br/>And 8 line breaks.<br/><br/><br/><br/><br/><br/><br/><br/>textbox -&gt;
            </text>
            <textbox>
                  <name>address</name>
            </textbox>
      </block>
</ajax>



I have a loop in one of my XSLT files that looks like this:
<xsl:for-each select="$thisNode/block | $thisNode/textbox | $thisNode/text">
                <xsl:choose>
                    <xsl:when test="name()='block'">
                          <xsl:call-template name="block">
                                <xsl:with-param name="thisNode" select="."/>
                           </xsl:call-template>
                    </xsl:when>
                    <xsl:when test="name()='textbox'">
                          <xsl:call-template name="textbox">
                                <xsl:with-param name="thisNode" select="."/>
                           </xsl:call-template>
                    </xsl:when>
                    <xsl:when test="name()='text'">
                          <xsl:call-template name="text">
                                <xsl:with-param name="thisNode" select="."/>
                           </xsl:call-template>
                    </xsl:when>
                </xsl:choose>
          </xsl:for-each>

I believe that the transformation is only doing the "block" section of my XML.

Within the block.xslt file I have this:
<xsl:call-template name="widgets">
      <xsl:with-param name="thisNode" select="$thisNode/*">
</xsl:call-template>


Please look at this link to see the issue (you will need this to see all of the xslt files too):
http://pdn.sieris.com/sieris/core8/test.xml
0
Comment
Question by:phobis
  • 6
  • 4
10 Comments
 
LVL 60

Expert Comment

by:Geert Bormans
Comment Utility
Hi phobis,

I have not tested fully,
but if I understand well,
there is something going wrong in line 29 of block.xslt
and I assume there will be a similar one in textbox.xslt and text.xslt

This call for the widgets template gets a nodeset,
where you would expect a single node

Try this instead of the single template call

            <xsl:for-each select="$thisNode/*">
                <xsl:call-template name="widgets">
                    <xsl:with-param name="thisNode" select="."/>
                </xsl:call-template>
            </xsl:for-each>

Cheers!

Geert
0
 
LVL 60

Expert Comment

by:Geert Bormans
Comment Utility
phobis,

I seriously don't understand why you are making things so complex
You use named templates passing a current node everywhere,
you could replace them with simple apply templates
I always assumed you had a higher reason to do all the complex templating yourself

but this construct
    <xsl:template name="widgets">
        <xsl:param name="thisNode"/>
        <xsl:for-each select="$thisNode/block | $thisNode/textbox | $thisNode/text">
                <xsl:choose>
                    <xsl:when test="name()='block'">
                          <xsl:call-template name="block">
                                <xsl:with-param name="thisNode" select="."/>
                           </xsl:call-template>
                    </xsl:when>
                    <xsl:when test="name()='textbox'">
                          <xsl:call-template name="textbox">
                                <xsl:with-param name="thisNode" select="."/>
                           </xsl:call-template>
                    </xsl:when>
                    <xsl:when test="name()='text'">
                          <xsl:call-template name="text">
                                <xsl:with-param name="thisNode" select="."/>
                           </xsl:call-template>
                    </xsl:when>
                </xsl:choose>
          </xsl:for-each>
    </xsl:template>
is completely unnecessary

                   <xsl:when test="name()='block'">
                          <xsl:call-template name="block">
                                <xsl:with-param name="thisNode" select="."/>
                           </xsl:call-template>
                    </xsl:when>
can be replaced with
    <xsl:apply-templates select="block"/>

and at the same time
<xsl:template name="block">.
    <xsl:param name="thisNode"/>
should be
<xsl:template match="block">

doing this, you get the current node as a context for free

I encourage you to rewrite the whole stuff
you will end up with half the code, at the most

0
 

Author Comment

by:phobis
Comment Utility
It seems like we are close now....

I have the modification out there:
http://pdn.sieris.com/sieris/core8/test.xml

I am still getting the same result though
0
 

Author Comment

by:phobis
Comment Utility
OK, I am sorry.

I am VERY VERY new at this. This would be my first time using XSLT. So I am sure I am making many mistakes. I have raised the point value on this issue.

Any help is greatly appriciated :)

I have made some changes on the site now... I want to make sure I have changes these things the way you expected me to do this?

Please let me know. Thank you.

http://pdn.sieris.com/sieris/core8/test.xml
0
 
LVL 60

Accepted Solution

by:
Geert Bormans earned 500 total points
Comment Utility
phobis,

well, no apologies required,
I have been following your process a while,
I even recommended a while back to pass the context node as $childNode if I remeber well
so given it the proper attention, I could have put you in the right direction earlier

What I now did is:
- I combined all your includes into one file
- I threw out all the named templates and am using proper
- and as a detail note, I changed the test "count(style) = 0" into "not(style)" and "count(style) > 0" into "style"

You can tear them back apart later if you want to
and the duplication of innerblock can be brought back into a named template for avoiding code repetition

but for now it is one chunk, so you can test to see if you can get this working as you like
and of course, so you can see that you understand apply-templates
apply-templates forces you to think hierachically whilst processing XSLT
and it gives you very clean modularised code

here we go, happy to get your comments

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
        doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" method="xml"
        omit-xml-declaration="yes"/>

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

    <xsl:template match="ajax">
        <xsl:apply-templates/>
     </xsl:template>
 
    <xsl:template match="block">
        <xsl:choose>
            <xsl:when test="not(style)">
                <div>
                    <xsl:choose>
                        <xsl:when test="not(refresh)">
                            <xsl:choose>
                                <xsl:when test="animate = 'true'">    
                                    <xsl:attribute name="class">contentAnimate</xsl:attribute>
                                </xsl:when>    
                            </xsl:choose>
                            <xsl:attribute name="id"><xsl:value-of select="id"/>-userdef-bobj</xsl:attribute>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:choose>
                                <xsl:when test="animate = 'true'">    
                                    <xsl:attribute name="class">contentRefreshAnimate</xsl:attribute>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:attribute name="class">contentRefresh</xsl:attribute>
                                </xsl:otherwise>
                            </xsl:choose>
                            <xsl:attribute name="id"><xsl:value-of select="id"/>-userdef-bobj-refresh<xsl:value-of select="refresh"/></xsl:attribute>
                        </xsl:otherwise>
                    </xsl:choose>
                        <xsl:apply-templates/>
                    <xsl:choose>
                        <xsl:when test="not(@refresh)">    
                        </xsl:when>
                        <xsl:otherwise>
                        </xsl:otherwise>
                    </xsl:choose>
                </div>
            </xsl:when>
            <xsl:otherwise>
                <div class="cssbox">
                    <xsl:attribute name="id"><xsl:value-of select="id"/>-bobj</xsl:attribute>
                    <div>
                        <xsl:choose>
                            <xsl:when test="not(title)">    
                                <xsl:attribute name="class">cssbox_nohead</xsl:attribute>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:attribute name="class">cssbox_head</xsl:attribute>
                            </xsl:otherwise>
                        </xsl:choose>
                        <xsl:attribute name="id"><xsl:value-of select="id"/>-bobj-header</xsl:attribute>
                        <h2>
                            <a>
                                <xsl:choose>
                                    <xsl:when test="not(refresh)">    
                                        <xsl:attribute name="name"><xsl:value-of select="id"/>-userdef-bobj</xsl:attribute>
                                    </xsl:when>
                                    <xsl:otherwise>
                                        <xsl:attribute name="name"><xsl:value-of select="id"/>-userdef-bobj-refresh<xsl:value-of select="refresh"/></xsl:attribute>
                                    </xsl:otherwise>
                                </xsl:choose>
                                <xsl:text disable-output-escaping="yes"></xsl:text>
                                <xsl:text> </xsl:text>
                                <xsl:value-of select="title"/>
                                <xsl:text> </xsl:text>
                                <xsl:text disable-output-escaping="yes"></xsl:text>
                            </a>
                        </h2>
                    </div>
                    <xsl:choose>
                        <xsl:when test="modifier">    
                            <div class="modifier">
                                <xsl:attribute name="id"><xsl:value-of select="id"/>-userdef-bobj-refresh__<xsl:value-of select="modifier"/></xsl:attribute>
                            </div>
                        </xsl:when>
                    </xsl:choose>
                    <div class="cssbox_body">
                        <xsl:attribute name="id"><xsl:value-of select="id"/>-bobj-body</xsl:attribute>
                        <div>
                            <xsl:choose>
                                <xsl:when test="not(refresh)">
                                    <xsl:choose>
                                        <xsl:when test="animate = 'true'">    
                                            <xsl:attribute name="class">contentAnimate</xsl:attribute>
                                        </xsl:when>    
                                    </xsl:choose>
                                    <xsl:attribute name="id"><xsl:value-of select="id"/>-userdef-bobj</xsl:attribute>
                                </xsl:when>
                                <xsl:otherwise>
                                    <xsl:choose>
                                        <xsl:when test="animate = 'true'">    
                                            <xsl:attribute name="class">contentRefreshAnimate</xsl:attribute>
                                        </xsl:when>
                                        <xsl:otherwise>
                                            <xsl:attribute name="class">contentRefresh</xsl:attribute>
                                        </xsl:otherwise>
                                    </xsl:choose>
                                    <xsl:attribute name="id"><xsl:value-of select="id"/>-userdef-bobj-refresh<xsl:value-of select="refresh"/></xsl:attribute>
                                </xsl:otherwise>
                            </xsl:choose>
                            <xsl:apply-templates/>
                            <xsl:choose>
                                <xsl:when test="not(@refresh)">    
                                </xsl:when>
                                <xsl:otherwise>
                                </xsl:otherwise>
                            </xsl:choose>
                        </div>
                    </div>
                </div>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
 
    <xsl:template match="text">
         <xsl:for-each select="node()">
            <xsl:choose>
                <xsl:when test="string-length(normalize-space(.)) &gt; 0">
                    <xsl:copy-of select="."/>
                </xsl:when>
                <xsl:otherwise><xsl:copy-of select="."/></xsl:otherwise>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>
   
    <xsl:template match="textbox">
        <div>
            <xsl:attribute name="name"><xsl:value-of select="id"/>-bobj</xsl:attribute>
            <input type="text">
                <xsl:attribute name="name"><xsl:value-of select="id"/>-input-bobj</xsl:attribute>
                <xsl:attribute name="disabled">disabled</xsl:attribute>
                <xsl:attribute name="size"></xsl:attribute>
                <xsl:attribute name="maxlength"></xsl:attribute>
                <xsl:attribute name="readonly">true</xsl:attribute>
            </input>
        </div>
    </xsl:template>
 
</xsl:stylesheet>

have fun,

Geert
0
Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

 

Author Comment

by:phobis
Comment Utility
OK.. I changed everything.. now the browser doesn't seem to understand that it is html.

take a look (this link is different than the other links)
http://pdn.sieris.com/sieris/core9/example-page.php
0
 
LVL 60

Expert Comment

by:Geert Bormans
Comment Utility
in the output method you choose the serialisation method for the stylesheet
it should have the same value for all included stylesheets
method="html"
it has the value "xml" for head.xslt
see what happens if you change that

XSLT is pretty modularised itself, due to all the templates that work a bit isolated (no side effects)
Debugging on multiple files is pretty hard
I suggest that you combine all templates in one file,
until debugging fase is over
(it is definitely easier for me, instead of downloading all those includes :-)

I generally only split functionality into other files after debugging is done
and I see some reuse of specific functionality,
if not includes are only adding complexity

cheers

Geert
0
 

Author Comment

by:phobis
Comment Utility
OK.. thank you....

I have it all in one xslt.

Could you tell me if you see anything that might be an issue?

http://pdn.sieris.com/sieris/core9/example-page.php


I had to add this to the xslt in order to keep it from showing all of the text of un-transformed elements:
<xsl:template match="*"></xsl:template>

Is there another way I could handel this?
0
 
LVL 60

Expert Comment

by:Geert Bormans
Comment Utility
> I have it all in one xslt.

Thanks

>I had to add this to the xslt in order to keep it from showing all of the text of un-transformed elements:
><xsl:template match="*"></xsl:template>

That will likely be the problem
People add an empty template to avoid text being spit out by the default templates
That is a good technique, but if this happens at a higher level,
all child nodes will be kept from processing too

You can use this technique, but make sure you have a template for each node that is important for you
AND for all the ancestors of these nodes

It could be wise to be selective in the apply-templates (give the select attribute a value)

I will now look into the stylesheet and make some suggestions

Geert
0
 
LVL 60

Expert Comment

by:Geert Bormans
Comment Utility
Hi,

just checked your page
The pure HTML output seems correct
I see something like this

static number -> 52.
Title 2
Content of block two.
widget3
More content    in this block.
Widget Four
 Hello World
 12/03/06 15:53:42 0.0034

After the page is loaded completely, all the above information is hidden behind the box colours
I think you have some absolute positioning in your CSS on divs with properties that hide the content of the actual html
so it might be that the bugs are not xslt related

cheers

Geert
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
Many times as a report developer I've been asked to display normalized data such as three rows with values Jack, Joe, and Bob as a single comma-separated string such as 'Jack, Joe, Bob', and vice versa.  Here's how to do it. 
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now