开发者

Converting an XML serialization back to java code

I know this questions might seem a little odd, but I want to make sure. One of my superiors is kind of convinced that there is a more or less easy way to convert the XML serialization of an object back to the java code that created it. I am, however, pretty sure that the best I can get is the object.

So basically my questions is: Is there any way to convert something like this

<java version开发者_StackOverflow社区="1.6.0_10" class="java.beans.XMLDecoder"> 
 <object class="javax.swing.JPanel"> 
  <void property="size"> 
   <object class="java.awt.Dimension"> 
    <int>42</int> 
    <int>23</int> 
   </object> 
  </void> 
 </object> 
</java>

back to something like

JPanel jPanel = new JPanel();
jPanel.setSize(42,23);

Thanks in advance.


Provided that all serialized objects comply to the java beans contract, you can re-create the process that the XML de-serializer follows to unmarshal the java objects, in order to recreate the code that goes with it.

Back in the golden XML days, I worked some projects that used similar processes to generate Java code from XML definitions.

Departing from your serialized model, you can use a XSL-T transformation to recreate the code that lead to the serialized objects. This process will create very linear code (as in non-modular), but you'll have what you're looking for.

An example to get you started: To process the XML you provided, you can use the following recursive transformation: copy/paste it & try it here: online XSL-T (the template is based on Xpath 1.0 to be able to use the online tool. Xpath 2.0 will improve the code in some areas, like string functions)

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xf="http://www.w3.org/2005/xpath-functions">

  <xsl:template match="object">
     <xsl:call-template name="objectClass" /> <xsl:value-of select="string(' ')" /> 
     <xsl:call-template name="objectNodeName" />
     = new <xsl:call-template name="objectClass" />(<xsl:call-template name="objectParams" />);

  <xsl:for-each select="*[@property]">
    <xsl:apply-templates />
    <xsl:call-template name="setProperty" />
  </xsl:for-each>

  </xsl:template>

  <xsl:template match="/" >
   <xsl:apply-templates match="/object" />
  </xsl:template>

  <xsl:template match="text()" />

  <xsl:template name="objectNodeName">
    <xsl:param name="node" select="." />
    <xsl:value-of select="translate($node/@class,'.','_')" />_<xsl:value-of select="count($node/ancestor-or-self::*)" />
  </xsl:template>

  <xsl:template name="setProperty">
    <xsl:call-template name="objectNodeName" > <xsl:with-param name="node" select="parent::node()"/></xsl:call-template>
.set<xsl:call-template name="capitalize"><xsl:with-param name="str" select="@property"/></xsl:call-template>(<xsl:call-template name="objectNodeName" > <xsl:with-param name="node" select="node()"/></xsl:call-template>);
  </xsl:template>

  <xsl:template name="objectClass">
    <xsl:param name="fqn" select="@class" />
    <xsl:value-of select="$fqn" />
  </xsl:template>

  <xsl:template name="objectParams">
    <xsl:for-each select="*[not(child::object)]">
     <xsl:if test="position() &gt; 1">,</xsl:if><xsl:value-of select="." />
     </xsl:for-each>
  </xsl:template>

  <xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
  <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

  <xsl:template name="capitalize">
    <xsl:param name="str" select="." />
    <xsl:value-of select="concat(translate(substring($str,1,1),$smallcase,$uppercase),substring($str,2))">
  </xsl:template>

</xsl:stylesheet>

Disclaimer: I tested the template on the sample provided and some variations of it, including some containign several more objects. I did not test deeper object nesting. It's an example and not a fully-functional XML Serialization to Java transformation, which is left as an exercise to the reader :-)


Yes, I think there are several ways to implement this. First of all you can use JAXB technology, read about it http://www.oracle.com/technetwork/articles/javase/index-140168.html#xmp1. Second way: you always can read xml in runtime (DOM, SAX) and create objects dynamically using reflection.


I don't think this is possible because if object class can be everything, how would you know what method to call to set size x to 42? Maybe there is a setter for this, maybe just a constructor or the number was calculated somehow.

The only possibility I can imagine is through the use of reflection, that's more or less the same frameworks like XStream do. So you can create the same object, but not the same code that was originally used to create it.


It is not that difficult. I am not sure how this would work with Swing class like JPanel, but since it is a Java bean, it should not be a problem to use some kind of XML library like XStream, which is one of the easiest way of how to do such things. Or you could use more verbose JAXB or XML Beans.

Edit: I'm sorry I didn't notice that there already is an XMLDecoder mentioned, and there seems to be an article on how to 'read JavaBean from XML file using XMLDecoder'.


I suspect that the superiors belief was poorly articulated and/or poorly understood. In particular, "the XML serialization of an object" may have been meant to refer to the schema, not the XML for a particular object, so that "convert the XML serialization of an object back to the java code that created it" would mean going from schema to marshalling code - JAXB's XJC, or similar.


I have never seen any sort of generalized technology that can reliably reconstruct the actual code instructions used to create an object based on a general XML serialization. What you have is stuff like JAXB, XStream or xmlbeans that can recreate an object based on XML serialized information. This is pretty evident when you think about it since there can be any number of ways to code an object to a specific state. Just knowing the state (which is really what the XML serialization is - the object's state at a certain point in time) is not enough to deduce HOW the object got to that state.

Also, there are many types of information that is transient in nature and not serializable (thread handles, sockets, window handles, device context etc etc etc) so serialization is not applicable to all objects/classes to begin with.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜