我知道这些问题看起来有点奇怪,但我想确定一下。 我的一个上级有点确信,将对象的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);
提前致谢。
答案 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() > 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序列化是什么 - 对象在某个时间点的状态)不足以推断出对象到达该状态的方式。
此外,有许多类型的信息本质上是瞬态的而不是可序列化的(线程句柄,套接字,窗口句柄,设备上下文等等),因此序列化不适用于所有对象/类开始。