A green bar for 16 bars


The latest entry in the “Do my work for me sucka!” series invloves my FOP memory flop. I need a declarative XSLT algortihm that can split an element using sub-elements or sub-sub elements for the split. In simpler words (why do I always start with the most complicated explanation?) I need to do things like break a single <foo/> element with about 160 <bar/> elements into 10 <foo/> elements each holding 16 <bar/>s. (If you’re an average techie that doesn’t know why 16 <bar/>s is relevant, click the link above. If you’re one of my homies who can’t figure out why bar comes after foo click this link. If you’re here because you’re drunk again then click this link.) It sounds simple until you remember, “Hey, I’m a Java programmer! Where are my variables at?” Or maybe it sounds simple and it is simple because you said, “Hey, I’ve been coding XSLT for years! That’s nothing!” (You don’t even have to say “Hey”. Just say, “send me that Veralex brochure”.) If that’s the case then complete your answer in the box below. Your solution will then be graded and your final score emailed to you within the hour. You’ll also be automatically entered in a drawing to win this car. Mercedes SLR

My problem has always been switching back and forth between imperative style Java programming and the more functional style of XSLT. Your problem is that you worried about my problems which creates problems when you’re working on an answer to this problem.

So how does it work out? We can write a template to match the <foo/> element. (In my case I’ve went overboard and wrote a template to match a parameterized element.) Then we can count the bars that we have underneath. Because we have no real variable assignments in our non-imperative language of preference we have to do a little math-magic and group the stuff we’re interested in. We group and select the first entry in each group to operate on. If you’re still thinking imperatively you’ll pull out your favorite trusty <xsl:for-each/> construct and go to town. Because I’m smarter than you I’m going to smack your fingers and tell you to put that looping nonsense away. (Bad programmer! Didn’t your mother teach you some declarative manners?) Anytime you think <xsl:for-each/> you should think <xsl:apply-templates/> and <xsl:template/> instead. When you get to be as good as I am you’ll write code like this: <xsl:apply-templates mode="split" select="$element-to-split/child::*[position() mod 16 = 1]"/> Then you whip up a template that matches anything with a mode named split and you’ll get down to business.

What’s your business in the split template?
In our split-mode template we spit our 16 bars. (Any of you got experience in dropping it like it’s hot? I do but I’m a little rusty.) Here’s what I get for my split mode.

    <xsl:template match="*" mode="split">
        <xsl:param name="parent"/>
        <xsl:element name="{name($parent)}">
            <xsl:copy-of select="$parent/@*"/>
            <xsl:copy-of select=". | following-sibling::*[position() < 16]"/>
        </xsl:element>
    </xsl:template>

Once again I get fancy with passing the parent as a parameter and all. So now we have a quick and dirty split template that takes the first bar element in each group and spits it with 15 additional bars. (Straight lyrical prowess son! Don’t nobody spit bars like I do!) What’s wrong with that? In my project I need to split an FO page-sequence that includes headers/footers and other nested stuff. I need the split to start from the nested <flow/> element. (Check the flow cousin! The rhyme flow!) I need all the stuff over the flow to come along in each split element. Then it gets better. I have to dig in the flow (after I grab the mic) and break out rows nested in tables. Here’s the real deal. I need this test to pass:

    public void testComplicatedSplit() throws Exception
    {
        String xml = "<doc>\n" +
                "\t<parent atttr1=\"some val\" attr2=\"newval\">\n" +
                "\t\t<table name=\"a\">\n" +
                "\t\t\t<row val=\"1\"/>\n" +
                "\t\t</table>\n" +
                "\t\t<table name=\"b\">\n" +
                "\t\t\t<row val=\"2\"/>\n" +
                "\t\t\t<row val=\"3\"/>\n" +
                "\t\t\t<row val=\"4\"/>\n" +
                "\t\t</table>\n" +
                "\t\t<table name=\"c\">\n" +
                "\t\t\t<row val=\"5\"/>\n" +
                "\t\t\t<row val=\"6\"/>\n" +
                "\t\t\t<row val=\"7\"/>\n" +
                "\t\t\t<row val=\"8\"/>\n" +
                "\t\t</table>\n" +
                "\t</parent>\n" +
                "</doc>";

        String expectedXml = "<doc>\n" +
                "\t<parent atttr1=\"some val\" attr2=\"newval\">\n" +
                "\t\t<table name=\"a\">\n" +
                "\t\t\t<row val=\"1\"/>\n" +
                "\t\t</table>\n" +
                "\t\t<table name=\"b\">\n" +
                "\t\t\t<row val=\"2\"/>\n" +
                "\t\t</table>\n" +
                "\t</parent>\n" +
                "\t<parent atttr1=\"some val\" attr2=\"newval\">\n" +
                "\t\t<table name=\"b\">\n" +
                "\t\t\t<row val=\"3\"/>\n" +
                "\t\t\t<row val=\"4\"/>\n" +
                "\t\t</table>\n" +
                "\t</parent>\n" +
                "\t<parent atttr1=\"some val\" attr2=\"newval\">\n" +
                "\t\t<table name=\"c\">\n" +
                "\t\t\t<row val=\"5\"/>\n" +
                "\t\t\t<row val=\"6\"/>\n" +
                "\t\t</table>\n" +
                "\t</parent>\n" +
                "\t<parent atttr1=\"some val\" attr2=\"newval\">\n" +
                "\t\t<table name=\"c\">\n" +
                "\t\t\t<row val=\"7\"/>\n" +
                "\t\t\t<row val=\"8\"/>\n" +
                "\t\t</table>\n" +
                "\t</parent>\n" +
                "</doc>";
        testStyleSheet(xml, splitterStylesheet, expectedXml);
    }

The test stylesheet method is selfexplanatory in that it takes the inputXml runs it with the stylesheet and asserts the result matches the output XML. I could include the implementation but then I’d be showing you too much. Oh ok, here’s a rough example of what it would look like:

    private void testStyleSheet(Document inputDocument, URL styleSheet, String expectedXML) throws Exception
    {
        String returnedXML = doTransform(styleSheet, inputDocument);
        assertIsValidDocument("Transform produced an invalid document.", returnedXML);
        assertXMLEquals(expectedXML, returnedXML);
    }


Now the doTransform() method is self explanatory and the assertIsValidDocument() can be commented out. I secretly went from string input to a Document so you’ll need an overload method to do the same. If you copy all of the above Java into a class that extends XMLTestCase (from the nice folks at XMLUnit) then your editor will help you stub out the missing method intentional style. (You do have an editor that supports intentional programming don’t you? Get one here. Intentional programming is a loaded term. What I’m referring to is described here.) Give it a shot, finish my work for me and I’ll be your best friend. (That might not go far with you but at least you’ll get bragging rights.) I gotta go and try to come up with the solution first so you don’t steal my right to gloat about how much smarter I am than you. Hit me up people…

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s