Solved

XSLT ----> preceding-sibling::

Posted on 2003-12-02
7
3,046 Views
Last Modified: 2013-11-18
Hello all,
            I am new to XSLT. I have a problem at hand where I have to insert a horizontal rule after a set of similar elements(all similar elements are already in sequential order). I was successful in doing it with the following code

                    <xsl:if test="((preceding-sibling::Insertion/Publication)[last()])">
                        <xsl:if test="not(Publication=((preceding-sibling::Insertion/Publication)[last()]))">
                            <tr>
                                <td colspan="20"><hr/></td>                                        
                            </tr>
                        </xsl:if>
                    </xsl:if>

PROBLEM: Though this works perfectly, whenever the XML file is huge, this code takes a considerable amount of time. I would be very grateful if anyone lead me to a better solution.

NOTE: The solution has to work fast on large XML file.

thanks,
Naveen.
0
Comment
Question by:naveen_damerla
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
  • 2
7 Comments
 
LVL 15

Expert Comment

by:dualsoul
ID: 9861390
hm...i don't understand well what do you want....
but why not to try get all Insertion/Publication one by one? like this:

<xsl:for-each select="Insertion/Publication">
          ...do something here with Publications if you want..........
</xsl:for-each>
<!-- insert horizonatal rule after all elements -->
<tr>
     <td colspan="20"><hr/></td>                                        
</tr>
........... continue processing....................

or didn't get what you want? if so please post more your xslt code, xml source and what do you want to get as output.
0
 

Author Comment

by:naveen_damerla
ID: 9861490
Maybe I wasnt clear enough
                                          Here I go, My XML looks like

           <Insertion>
            <RevisionType></RevisionType>
            <City>Ventura</City>
            <State>CA</State>
            <Publication>Ventura County Star</Publication>
              .
              . //more elements here
            </Insertion>

            <Insertion>
            <RevisionType></RevisionType>
            <City>Ventura</City>
            <State>CA</State>
            <Publication>Anothet County Star</Publication>
             .
             .//more elements here
            </Insertion>

XSLT IS:

     <xsl:if test="((preceding-sibling::Insertion/Publication)[last()])">
                     <xsl:if test="not(Publication=((preceding-sibling::Insertion/Publication)[last()]))">
                            <tr>
                                <td colspan="20"><hr/></td>                                        
                            </tr>
                        </xsl:if>
                    </xsl:if>

What I is want is a horizontal rule """" if """" the publication name is the not the same....and do nothing if it is the same.

That being said my XML files are xtremely huge, so......though the my XSLT works pefectly.....I would like to have a faster alternative.

thanks,
Naveen.
0
 
LVL 26

Accepted Solution

by:
rdcpro earned 500 total points
ID: 9861501
Use an XSLT key, and index all the nodes by the aspect you use to determine similarity.  Then you simply have to test if the current node is a new unique node, and insert the horizontal rule:

Using this XML:
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="muenchrule.xslt"?>
<insertion>
    <publication>Foo</publication>
    <publication>Foo</publication>
    <publication>Foo</publication>
    <publication>Foo</publication>
    <publication>Foo</publication>
    <publication>Foo</publication>
    <publication>Foo</publication>
    <publication>Bar</publication>
    <publication>Bar</publication>
    <publication>Bar</publication>
    <publication>Bar</publication>
    <publication>Bar</publication>
    <publication>Bar</publication>
    <publication>Bar</publication>
    <publication>Bar</publication>
    <publication>Bar</publication>
    <publication>Snafu</publication>
    <publication>Snafu</publication>
    <publication>Snafu</publication>
    <publication>Snafu</publication>
    <publication>Snafu</publication>
    <publication>Snafu</publication>
</insertion>

And this XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:key name="kRule" match="publication" use="."/>
    <xsl:template match="insertion">
        <Table>
            <xsl:apply-templates select="publication"/>
        </Table>
    </xsl:template>
    <xsl:template match="publication">
        <xsl:if test="generate-id() = generate-id(key('kRule', .)) and position() !=1">
            <tr>
                <td colspan="20"><hr/></td>
            </tr>
        </xsl:if>
            <tr>
                <td colspan="20"><xsl:value-of select="."/></td>
            </tr>
    </xsl:template>
</xsl:stylesheet>

You get a horizontal rule between each unique group, but not before the first one.  This should work fairly quickly for even large sets of nodes.

Regards,
Mike Sharp
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 15

Expert Comment

by:dualsoul
ID: 9861611
>That being said my XML files are xtremely huge, so......though the my XSLT works pefectly.....I would like to have a faster alternative.

may be Mike's suggestion helps you, i think.
 but if you have trouble with perfomance, you should know XSLT is not scalable solution...so if you think your xml files can enlarge in future may be you should think about another architecture...XQuery for instance
0
 

Author Comment

by:naveen_damerla
ID: 9862139
Thank you rdcpro,
 
Your answer sounds really promising(havent tried it)....but I am a completely new to XSLT, this being my 2nd day.......AT the risk of sounding dumb, I would like to ask one more thing....
         If there is already a <xsl:for-each select="Insertions/Insertion">
in the XSLT, how would the answer change

plz note: there will be 500+ elements in the insertions node.


XML looks like:
------------------
<insertions>
        <Insertion>
            <RevisionType></RevisionType>
            <City>Ventura</City>
            <State>CA</State>
            <Publication>Ventura County Star</Publication>
              .
              . //more elements here
            </Insertion>

            <Insertion>
            <RevisionType></RevisionType>
            <City>Ventura</City>
            <State>CA</State>
            <Publication>Anothet County Star</Publication>
             .
             .//more elements here
            </Insertion>

             //500 more insertion elements
 </insertions>

XSLT like:
---------------
<xsl:for-each select="Insertions/Insertion">
                    <xsl:if test="((preceding-sibling::Insertion/Publication)[last()])">
                    <xsl:if test="not(Publication=((preceding-sibling::Insertion/Publication)[last()]))">
                            <!-- inserting horizontal rule-->
                            <tr>
                                <td colspan="20"><hr/></td>                                        
                            </tr>
                        </xsl:if>
                    </xsl:if>
                <tr>
                 <!-- REST OF MY CODE HERE-->
                </tr>


please advise,
thank you rdcpro
Naveen.
0
 
LVL 26

Assisted Solution

by:rdcpro
rdcpro earned 500 total points
ID: 9863180
Well, in that case only the path for the use attribute, and the path to the key() change:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/>
    <xsl:key name="kRule" match="insertion" use="publication"/>
    <xsl:template match="insertions">
    Number of Insertions:  <xsl:value-of select="count(insertion)"/>
        <Table>
            <xsl:for-each select="insertion">
                <xsl:if test="generate-id() = generate-id(key('kRule', publication)) and position() !=1">
                    <tr>
                        <td colspan="20"><hr/></td>
                    </tr>
                </xsl:if>
                    <tr>
                        <td colspan="20"><xsl:value-of select="publication"/></td>
                    </tr>
                   
            </xsl:for-each>
       </Table>
    </xsl:template>
</xsl:stylesheet>

Note that my XML is not the same case as yours...that is, insertion not Insertion...so watch out.

But with 822 <inserton> elements, it transforms nearly instantly on my desktop.  Parsing the XML is probably going to be a major portion of the overhead, and if you use FreeThreadDomDocument, and caching, you might be surprised how well it scales, assuming efficient XSLT.

This technique is Muenchian grouping, and I have examples and a tutorial on my site:
Code example:
http://dev.rdcpro.com/Members/rdcpro/snippets/columnrowgrouping/
tutorial:
http://dev.rdcpro.com/zones/xml/xslt/faqroot/faq-grouping-1.1

Caching techniques for ASP:
http://dev.rdcpro.com/Members/rdcpro/snippets/cachingtemplates/


Regards,
Mike Sharp
0
 

Author Comment

by:naveen_damerla
ID: 9884127
Thank u rdcpro. I just plugged in the partial code at the right place and PRESTO!!.....evrything works.....and 43 pages of PDF generation was under 2 minutes.

thanks again.....
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Word files to Wordpress Posts 2 73
XSL - substring between 2 commas 12 24
How does proportional-column-width work in xsl fo 4 41
Need a modeling tool 2 42
Preface In the first article: A Better Website Login System (http://www.experts-exchange.com/A_2902.html) I introduced the EE Collaborative Login System and its intended purpose. In this article I will discuss some of the design consideratio…
This article covers the basics of the Sass, which is a CSS extension language. You will learn about variables, mixins, and nesting.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
Video by: Mark
This lesson goes over how to construct ordered and unordered lists and how to create hyperlinks.

733 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