Merging schema xml with data xml with Java

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • bonjo
    New Member
    • Oct 2013
    • 12

    Merging schema xml with data xml with Java

    Hello everyone,
    I wish, based on two xml:
    1. ui.xml: defines a layout, based on variables/conditions in its attributes, such as:
    Code:
    <root>
    <item title="if data/gender = 'female': Ms.; else: Mr." />
    </root>
    2. data.xml: defines actual data came from another data source:
    Code:
    <data>
    <gender>male</gender>
    </data>
    to merge the two into one result.xml, which, in that case would be:
    Code:
    <root>
    <item title="Mr." />
    </root>
    I started from the end, as i think its clearer, I want to define attributes values based on what I have in my data.
    Of course, the language I have there is just some pseudo -code, it can be anything, as long as its readable :)
    I have read about mustache / handlebars implementations in java, which is more or less what I need (some sort of templating engine) but sadly, those are logic-less approaches.
    I need less-logic or full-of-logic kind of approach.
    What would you advice based on your knowledge?
  • chaarmann
    Recognized Expert Contributor
    • Nov 2007
    • 785

    #2
    Read in both XMLs as DOM-tree in Java (see org.w3c.dom.Doc ument).
    Then merge them into a resulting DOM-tree.
    (You must provide the merge logic by your own java code. Using XPath is very helpful doing it.)
    Then save the resulting DOM-tree as an XML file (using TransformerFact ory to get a transformer instance and then using its transform() method).

    Comment

    • bonjo
      New Member
      • Oct 2013
      • 12

      #3
      So I should, after having a dom-tree, use xpath in java to select all attributes (according to my example, all 'title' attributes), and in those attributes i should write xpath code, and evaluate it on my second (data) dom-tree?
      then, replace the attribute's value to the evaluated one?
      I can see how I can pull information, but how can I tell in xpath if statements, so that if it found that a certain value is 'X', assign 'Y' to that attribute.
      Im not sure it will fit to my needs.
      Could you be a bit more specific? Im not quite sure how the evaluation during merge process occurs.

      I

      Comment

      • chaarmann
        Recognized Expert Contributor
        • Nov 2007
        • 785

        #4
        You got it right. Just get the value of the attribute from the DOM as a String. In your example you would store "if data/gender = 'female': Ms.; else: Mr." in the variable (for example) named scriptString. I don't recognize this language. But let us assume it is javascript or xpath.
        If it is javascript, you could use a scripting engine to evaluate this expression:
        Code:
        ScriptEngineManager factory = new ScriptEngineManager();
         ScriptEngine engine = factory.getEngineByName("JavaScript");
         engine.eval(scriptString);
        If it is xpath, you could use it directly in your "xpath.evaluate (scriptString)" . It is possible to make if-else-statements with xpath. Example:
        Code:
        if (/data[@gender='female'])
           then 'Ms.' 
           else 'Mr.'

        Comment

        • bonjo
          New Member
          • Oct 2013
          • 12

          #5
          I prefer using xpath engine ( I guess runtime will be much better comparing to js engine) But its not accepting those if statements.
          I try the following:
          exp = "if (/row/field[@name='service']) then 'Ms.' else 'Mr.'";
          res = xPath.compile(e xp).evaluate(xm lDocument);
          but then I get javax.xml.trans form.Transforme rException: Could not find function: if

          Is it, for sure, exists in java xpath engine?

          Comment

          • chaarmann
            Recognized Expert Contributor
            • Nov 2007
            • 785

            #6
            If-else-syntax exists only in Xpath 2.0 and up.
            If you are using the old Xpath 1.0, you can simulate it with:
            Code:
            concat(substring('Ms.', 1 div boolean(/data[@gender='female'])),
                   substring('Mr.', 1 div not(/data[@gender='female']))
                  )
            Why do you use "/row/field[@name='service'])" instead of "/data[@gender='female ']" as given in examples above?

            Comment

            • bonjo
              New Member
              • Oct 2013
              • 12

              #7
              Yes, That was a mistake.
              Using XPath 1.0 seems very problematic.
              perhaps I should look at a different direction.
              I also need the strength to do if-elseif-elseif-else, and maybe if-if-if statements.
              how severe in performance is using the ScriptEngine to evaluate javascript expressions?

              Comment

              • chaarmann
                Recognized Expert Contributor
                • Nov 2007
                • 785

                #8
                javascript speed was improved rapidly over the years. I remember the first Netscape browsers where I felt it was thousand times slower than nowadays.
                The latest javascript engine for Firefox was also a major performance step . It is much faster than the one in Internet Explorer 8. My javascript game that I programmed a few years ago, and where I used many tricks to speed it up, is now running fast like hell!

                I would say, give it a try.
                I am not sure, but I bet it is much faster than xpath which did not have major performace improvements over the years.

                You can do us a favor and measure the performance for both xpath and javascript and then post it here. I am eager to hear if my assumption is right.

                Comment

                • bonjo
                  New Member
                  • Oct 2013
                  • 12

                  #9
                  I'd gladly try to measure that, but first I need to understand how to accomplish it :-)
                  Its a bit of a mixup, as I cant really use only JS to iterate over my data.xml and evaluate statements over it.
                  I will still need, this way or another, to use some kind of xpath, just in javascript.
                  either that, or I will create some multi dimensional array holding all my xml elements and their attributes,
                  and evaluate the javascript together with my data structure.

                  Now, after I wrote it down, it sounds like one hell of a mess.

                  Comment

                  • chaarmann
                    Recognized Expert Contributor
                    • Nov 2007
                    • 785

                    #10
                    You are right, it is more work to do it in JS. And you can't reference variables like "/data/gender", you must use "gender" directly in your expression. How do you get the value for "gender" to set it before executing the JS? Most likely using xpath on your data-holding-XML.
                    Or use a converter to convert your data-holding-XML to JSON and use that in your JS-snippet.

                    So avoid premature optimization and start doing it with xpath, and only in case the performance is unacceptable bad at some hotspots, use JS there.
                    I guess JS would give you a performance boost only for
                    long and complicated expressions, but not for simple if-else constructs.

                    Comment

                    • bonjo
                      New Member
                      • Oct 2013
                      • 12

                      #11
                      Im still investigating my options.
                      I might prefer the JS engine after all.
                      but I wonder what is the best way to reconstruct my xml file to a data structure that JS Engine will work easily with.
                      What is it that you say about json? can you explain a bit further that point?

                      Comment

                      • bonjo
                        New Member
                        • Oct 2013
                        • 12

                        #12
                        Also, another interesting question, is it possible to debug the ScriptEngine instructions?
                        Same as you debug a js in browser / attach to process in Script mode with VS?

                        Comment

                        • chaarmann
                          Recognized Expert Contributor
                          • Nov 2007
                          • 785

                          #13
                          If you can create the GUI.xml yourself, and only the data.xml is given, then I would not use any methods described above.

                          Just change your GUI.xml slightly to make a GUI.xsl out of it.
                          Read about XSL and XSLT to know the syntax. XSL is the standard way to do transformation tasks like yours and there are also a lot of online-xsl-converter for easy testing.

                          Then you can use java to do the transformation via TransformerFact ory.
                          Code:
                          public void transform(String dataXml, String inputXsl, String outputXml)
                          	            throws TransformerConfigurationException,
                          	            TransformerException
                          	    {
                          	 
                          	        TransformerFactory factory = TransformerFactory.newInstance();
                          	        StreamSource xslStream = new StreamSource(inputXsl);
                          	        Transformer transformer = factory.newTransformer(xslStream);
                          	        StreamSource in = new StreamSource(dataXml);
                          	        StreamResult out = new StreamResult(outputXml);
                          	        transformer.transform(in, out);
                          	        System.out.println("The generated XML file is:" + outputXml);
                          	    }

                          Comment

                          • bonjo
                            New Member
                            • Oct 2013
                            • 12

                            #14
                            Well, I promised to update about time measurements.
                            so, I tried two approaches:
                            1. Having an xml with embedded JS.
                            I construct a dom-tree, locate js scripts and run it.
                            2. Having an xsl file. using TransformerFact ory to create an output xml of it.

                            Simulating with 10runs gives the following time (seconds):
                            JS: 0.03374
                            XSL: 0.04
                            Thats already very close.
                            When going for larger runs, it gets better (10000 runs):
                            JS: 0.00217
                            XSL: 0.01

                            I guess its some static variables and things i tried to manage better.
                            Perhaps the ScriptEngine is better than the old XPath.

                            Comment

                            • chaarmann
                              Recognized Expert Contributor
                              • Nov 2007
                              • 785

                              #15
                              Thank you for the statistics.
                              Can you post the testing code?

                              Comment

                              Working...