Discussions

News: Getting Groovy with XML

  1. Getting Groovy with XML (8 messages)

    Working with XML has been notoriously difficult. You normally don't want to drop to the level of SAX or DOM, so many open source projects have come around to help us out. Groovy has a lot of good XML support itself, and this article goes into the details of how to suck in, munge, and spew out XML.

    Conclusion
    XML is pretty cool stuff, and the more we use it, the more we need to think about how to make it easier to use. We need to think about ways to reduce the XML infrastructure work for ourselves and our customers.

    Now, I don't seriously think that people will start replacing XSLT with Groovy code. But I do think that this article should spur your imagination with ideas about how you can use a flexible scripting language like Groovy to simplify your application and to make it more extensible. When integrating Groovy into your application is as simple as creating an interpreter and asking the class loader for a class, you have to think about all of the things you can do in the script layer as part of rapid prototyping, things that can then be brought back into the Java layer for efficiency.

    Adding dynamic scripting-language support to your application is at your fingertips. Give it a go!
    Getting Groovy with XML

    Threaded Messages (8)

  2. His final solution still has a lot of boiler plate code.
    The following is a ruby script I banged together in a few min. that does the exact same thing. Does Groovy have anything like this?

    # File: rexml_test.rb
    # Date: 08/13/04

    require 'rexml/document'

    def calculateAmounts( doc )
    amounts = Hash.new

    doc.root.each_element("account") { |account|
    sum = 0
    account.each_element("transaction") { |transaction|
    sum += transaction.attributes["amount"].to_i
    }

    amounts[ account.attributes["id"] ] = sum
    }

    return amounts
    end

    doc = REXML::Document.new( File.open( "test_data.xml" ) )
    amounts = calculateAmounts( doc )

    puts "a = " + amounts["a"].to_s
    puts "b = " + amounts["b"].to_s
  3. Now the Java solution...[ Go to top ]

    Ruby solution is cool. Now the Java solution, if not matching, then at least as close as possible to the no-nonsense Ruby solution. :)

    Take a look at this:
    http://www.devx.com/Java/Article/16571/0 - for the example in the beginning of this article, the following operations would suffice:

    reading the data:

    <code>
    XmlData doc = new XmlData(new File("my.xml");
    </code>

    retrieving data in Java:

    <code>
    int sumA = 0;
    XmlData account = doc.getKid("account", "a");

    for (XmlData trans : account.getKids("transaction)) {
      sumA = Integer.parseInt(trans.getAttribute("amount"));
    }
    </code>

    Freely available on myjavatools.com

    :)
  4. His final solution still has a lot of boiler plate code.The following is a ruby script I banged together in a few min. that does the exact same thing. Does Groovy have anything like this?# File: rexml_test.rb# Date: 08/13/04require 'rexml/document'def calculateAmounts( doc ) amounts = Hash.new doc.root.each_element("account") { |account| sum = 0 account.each_element("transaction") { |transaction| sum += transaction.attributes["amount"].to_i } amounts[ account.attributes["id"] ] = sum } return amountsenddoc = REXML::Document.new( File.open( "test_data.xml" ) )amounts = calculateAmounts( doc )puts "a = " + amounts["a"].to_sputs "b = " + amounts["b"].to_s
    Or, a less verbose solution:

    def calculate_accounts(data_file)
      require 'rexml/document'
      doc = REXML::Document.new(File.read(data_file))

      amounts = Hash.new(0) # Default value for amounts.

      doc.root.each_element("account/transaction") do |tx|
        amounts[tx.parent.attributes['id']] += tx.attributes['amount'].to_i
      end

      return amounts
    end

    amounts = calculate_accounts('test_data.xml')
    puts "a = %s" % amounts['a']
    puts "b = %s" % amounts['b']
  5. XSLT is still better[ Go to top ]

    <xsl:template match="account">
    <xsl:value-of select="@id" />
    <xsl:text> = </xsl:text>
    <xsl:value-of select="sum(./transaction/@amount)" />
    </xsl:template>

    Unfortunately the author dismisses XSLT as "hard to learn, follows an uncommon functional programming paradigm, and overkill for small problems" (quoting from the article). What happened to using the right tool for the job? How is the above overkill? It could be argued it is in fact easier.

    I wish the author had mentioned XSL is still the best tool for almost anything XML-related, small problems or large ones. Surely XSL is verbose, awkward, and its "functional programming paradigm" is uncommon to those without a CS degree, but it shines at this.

    Maybe an example better tailored to Groovy's strengths would have been more interesting. I'm not convinced I should be using Groovy for XML processing, so what's it good for?
  6. XSLT is still better[ Go to top ]

    <xsl:template match="account"> <xsl:value-of select="@id" /> <xsl:text> = </xsl:text> <xsl:value-of select="sum(./transaction/@amount)" /></xsl:template>
    I agree that "hard to learn" and "follows an uncommon functional programming paradigm" are not good enough reasons to "dismiss the right tool for the right job."

    However, the above XSLT is just plain UGLY (readability, maintenance, etc.)
  7. XSLT is still better[ Go to top ]

    <xsl:template match="account"> <xsl:value-of select="@id" /> <xsl:text> = </xsl:text> <xsl:value-of select="sum(./transaction/@amount)" /></xsl:template>
    I agree that "hard to learn" and "follows an uncommon functional programming paradigm" are not good enough reasons to "dismiss the right tool for the right job."However, the above XSLT is just plain UGLY (readability, maintenance, etc.)
    Somehow I feel that Groovy way to calculate amount:
    class AmountAdder implements GroovyNodeIterator
    {
        public Object process( DOMNodeGroovyObject doc )
        {
            accountValues = [:];
            for( accountNode in doc.xpath( "/transactions/account" ) )
            {
                accountValues[ accountNode.id ] = 0;
                for( transNode in accountNode.xpath( "transaction" ) )
                {
                    accountValues[ accountNode.id ] +=
                        Integer.valueOf( transNode.amount );
                }
            }
            return accountValues;
        }
    }
    is much more complicated "readability, maintenance" wise than XSL way "<xsl:value-of select="sum(./transaction/@amount)" />".

    I definitely prefer standards based XSL to some proprietary solutions...
    Not sure what Groovy is good for.
  8. why groovy vs xslt?[ Go to top ]

    By seeing the example in groovy web site, seems like it is totally new scripting language.

    And someone try to use it to replate XSLT....

    however i feel that to learn groovy may take a lot of time, why not try some template engine like freemarker if really want to replace xslt?

    and template engine is easily to integrate with existing java application.
  9. Freemarker can handle this too[ Go to top ]

    http://freemarker.sourceforge.net/docs/xgui.html

    And you can run it as an ant task, for example ;-)