Преобразование сериализации XML обратно в код Java - PullRequest
2 голосов
/ 12 июля 2011

Я знаю, что эти вопросы могут показаться немного странными, но я хочу убедиться.Один из моих начальников убежден, что есть более-менее простой способ преобразовать сериализацию 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 ]

3 голосов
/ 13 июля 2011

При условии, что все сериализованные объекты соответствуют контракту Java-бинов, вы можете воссоздать процесс, которым XML-десериализатор следует, чтобы демонтировать java-объекты, чтобы воссоздать код, который идет с ним.

В золотые дни XML я работал над некоторыми проектами, в которых использовались похожие процессы для генерации кода Java из определений XML.

Исходя из вашей сериализованной модели, вы можете использовать преобразование 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() &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>

Отказ от ответственности: я протестировал шаблон на предоставленном образце и некоторые его варианты, в том числе некоторые содержат еще несколько объектов.Я не проверял более глубокое вложение объектов.Это пример, а не полностью функциональное преобразование XML-сериализации в Java, которое оставлено читателю в качестве упражнения: -)

0 голосов
/ 13 июля 2011

Я подозреваю, что вера начальства была плохо сформулирована и / или плохо понята.В частности, «сериализация XML объекта» могла означать ссылку на схему, а не XML для конкретного объекта, так что «преобразование сериализации XML объекта обратно в код Java, который его создал» означало быпереход от схемы к маршалинг-коду - XJC JAXB или аналогичный.

0 голосов
/ 12 июля 2011

Я никогда не видел какой-либо обобщенной технологии, которая могла бы надежно реконструировать действительные инструкции кода , используемые для создания объекта на основе общей сериализации XML.У вас есть такие вещи, как JAXB, XStream или xmlbeans, которые могут воссоздать объект на основе сериализованной информации XML.Это довольно очевидно, когда вы думаете об этом, поскольку может быть любое количество способов кодирования объекта в определенное состояние.Простого знания состояния (которое в действительности представляет собой сериализацию XML - состояние объекта в определенный момент времени) недостаточно, чтобы определить, КАК объект попал в это состояние.

Кроме того, существует много типов информации, которая носит временный характер и не сериализуется (дескрипторы потоков, сокеты, дескрипторы окон, контекст устройства и т. Д. И т. Д.), Поэтому сериализация не применима ко всем объектам / классам с самого начала.

0 голосов
/ 12 июля 2011

Я не думаю, что это возможно, потому что, если класс объекта может быть всем, как бы вы узнали, какой метод вызывать, чтобы установить размер x равным 42? Может быть, для этого есть установщик, может быть, просто конструктор или число было вычислено каким-то образом.

Единственная возможность, которую я могу себе представить, - это использование отражения, это более или менее те же фреймворки, что и в XStream. Таким образом, вы можете создать тот же объект, но не тот же код, который изначально использовался для его создания.

0 голосов
/ 12 июля 2011

Это не так сложно.Я не уверен, как это будет работать с классом Swing, таким как JPanel, но, поскольку это Java-бин, не должно быть проблемой использование какой-либо библиотеки XML, такой как XStream , которая является одной изсамый простой способ, как сделать такие вещи.Или вы можете использовать более подробный JAXB или XML Beans .

Редактировать: Извините, я не заметил, что уже упоминался XMLDecoder, и Кажется, есть статья о том, как «читать JavaBean из XML-файла с использованием XMLDecoder».

0 голосов
/ 12 июля 2011

Да, я думаю, что есть несколько способов реализовать это.Прежде всего вы можете использовать технологию JAXB, прочитайте об этом http://www.oracle.com/technetwork/articles/javase/index-140168.html#xmp1. Второй способ: вы всегда можете читать XML во время выполнения (DOM, SAX) и динамически создавать объекты с помощью отражения.

...