Solved

XSLT ----> preceding-sibling::

Posted on 2003-12-02
7
3,030 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
  • 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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Styling your websites can become very complex. Here I'll show how SASS can help you better organize, maintain and reuse your CSS code.
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

709 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