将 XML 序列化转换回 Java 代码

发布于 2024-11-19 14:51:30 字数 589 浏览 2 评论 0原文

我知道这个问题可能看起来有点奇怪,但我想确定一下。 我的一位上级确信有一种或多或少简单的方法可以将对象的 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);

提前致谢的内容。

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="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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

瞳孔里扚悲伤 2024-11-26 14:51:30

假设所有序列化对象都遵守 java beans 契约,您可以重新创建 XML 反序列化器解组 java 对象的过程,以便重新创建与之相关的代码。

早在 XML 的黄金时代,我就曾参与过一些使用类似流程从 XML 定义生成 Java 代码的项目。

与序列化模型不同,您可以使用 XSL-T 转换来重新创建生成序列化对象的代码。此过程将创建非常线性的代码(如非模块化代码),但您将获得所需的内容。

入门示例:要处理您提供的 XML,您可以使用以下递归转换:复制/粘贴并复制/粘贴它。在这里尝试一下:在线 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>

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

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() > 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 :-)

甜中书 2024-11-26 14:51:30

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

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.

暮倦 2024-11-26 14:51:30

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

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

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.

小清晰的声音 2024-11-26 14:51:30

这并不难。我不确定这如何与 JPanel 这样的 Swing 类一起使用,但由于它是一个 Java bean,因此使用某种 XML 库(例如 XStream,这是执行此类操作的最简单方法之一。或者您可以使用更详细的 JAXB 或 XML Bean

编辑:抱歉,我没有注意到已经提到了 XMLDecoder,并且 似乎有一篇关于如何“使用 XMLDecoder 从 XML 文件读取 JavaBean”的文章。

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'.

給妳壹絲溫柔 2024-11-26 14:51:30

我怀疑上级的信念表达不清晰和/或理解不深。特别是,“对象的 XML 序列化”可能指的是架构,而不是特定对象的 XML,因此“将对象的 XML 序列化转换回创建它的 java 代码”意味着从模式到编组代码 - JAXB 的 XJC 或类似的。

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.

芸娘子的小脾气 2024-11-26 14:51:30

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文