将XML序列化转换回java代码

时间:2011-07-12 09:31:18

标签: java code-generation xml-deserialization

我知道这些问题看起来有点奇怪,但我想确定一下。 我的一个上级有点确信,将对象的XML序列化转换回创建它的java代码或多或少是简单的方法。但是,我非常确定我能得到的最好的是对象。

基本上我的问题是:有没有办法转换像这样的东西

<java version="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>

回到类似

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

提前致谢。

6 个答案:

答案 0 :(得分:3)

如果所有序列化对象都符合java bean协定,则可以重新创建XML反序列化程序所遵循的进程以解组java对象,以便重新创建与其一起使用的代码。

回到金色的XML时代,我参与了一些使用类似过程从XML定义生成Java代码的项目。

从序列化模型中脱离,您可以使用XSL-T转换来重新创建导致序列化对象的代码。这个过程将创建非常线性的代码(如非模块化的),但是你将拥有你想要的东西。

开始使用的示例:要处理您提供的XML,您可以使用以下递归转换:复制/粘贴它&amp;在这里试试:online XSL-T (该模板基于Xpath 1.0,可以使用在线工具.Xpath 2.0将改善某些领域的代码,如字符串函数)

<?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>

免责声明:我在提供的示例及其中的一些变体上测试了模板,包括一些包含更多对象的模板。我没有测试更深的对象嵌套。这是一个例子,而不是Java转换的全功能XML Serialization,它留给读者一个练习: - )

答案 1 :(得分:0)

是的,我认为有几种方法可以实现这一点。首先,您可以使用JAXB技术,阅读它http://www.oracle.com/technetwork/articles/javase/index-140168.html#xmp1。 第二种方式:你总是可以在运行时读取xml(DOM,SAX)并使用反射动态创建对象。

答案 2 :(得分:0)

这并不困难。我不确定这对于像JPanel这样的Swing类是如何工作的,但由于它是一个Java bean,因此使用像XStream这样的某种XML库应该不会有问题。如何做这些事情最简单的方法。或者您可以使用更详细的JAXB或XML Beans

编辑:对不起,我没有注意到已经提到了XMLDecoder,并且there seems to be有一篇关于如何使用XMLDecoder从XML文件中读取JavaBean的文章。

答案 3 :(得分:0)

我不认为这是可能的,因为如果对象类可以是一切,你怎么知道调用什么方法将x大小设置为42?也许有一个这样的setter,也许只是一个构造函数或者数字是以某种方式计算的。

我能想象的唯一可能性是通过使用反射,这或多或少是像XStream那样的框架。因此,您可以创建相同的对象,但不能创建最初用于创建它的相同代码。

答案 4 :(得分:0)

我怀疑上司的信念很难表达和/或知之甚少。特别是,“对象的XML序列化”可能是指模式,而不是特定对象的XML,因此“将对象的XML序列化转换回创建它的Java代码”将意味着从模式到编组代码 - JAXB的XJC,或类似的。

答案 5 :(得分:-1)

我从未见过任何可以可靠地重建用于基于常规XML序列化创建对象的代码指令的通用技术。您拥有的是JAXB,XStream或xmlbeans之类的东西,可以根据XML序列化信息重新创建对象。当您考虑它时,这是非常明显的,因为可以有多种方法将对象编码为特定状态。只知道状态(实际上是XML序列化是什么 - 对象在某个时间点的状态)不足以推断出对象到达该状态的方式。

此外,有许多类型的信息本质上是瞬态的而不是可序列化的(线程句柄,套接字,窗口句柄,设备上下文等等),因此序列化不适用于所有对象/类开始。