Как заставить jaxb игнорировать определенные данные во время демаршаллинга - PullRequest
3 голосов
/ 25 февраля 2011

У меня есть XML-структура «Фильтр», которая разбирается в Java-классе «Фильтр».

Состояние XML выглядит примерно так:

<filter>
  <propertyType>
    <propertyName>prop1</propertyName>
    <propertyValue>val1</propertyValue>
  </propertyType>
  <propertyType>
    <propertyName>prop2</propertyName>
    <propertyValue>val2</propertyValue>
  </propertyType>
</filter>

Обычно это прекрасно работает.

Однако существуют определенные ситуации, когда одно из этих значений свойства само содержит структуру xml (см. Второе свойство value ниже):

<filter>
  <propertyType>
    <propertyName>prop1</propertyName>
    <propertyValue>val1</propertyValue>
  </propertyType>
  <propertyType>
    <propertyName>prop2</propertyName>
    <propertyValue><nodeA><nodeB>valB</nodeB></nodeA></propertyValue>
  </propertyType>
</filter>

Проблема здесь в том, что после демаршаллинга этой структуры propertyValue имеет значение null.

Я хотел бы просто иметь возможность, чтобы демаршаллинг игнорировал этот XML-выглядящий код и рассматривал его как простое строковое значение.

Кто-нибудь знает, как мне это сделать? Спасибо за любой ответ!

Ответы [ 3 ]

1 голос
/ 25 февраля 2011

Как насчет аннотации использования "@XmlAnyElement"? Вы можете получить экземпляр org.w3c.dom.Element. Текстовые данные должны быть в состоянии получить, управляя этим экземпляром.

class PropertyType {
    private String propertyName;
    // private String propertyValue; // comment out
    @XmlAnyElement(lax=true)
    private List<org.w3c.dom.Element> propertyValue; // Adding this
}

Пример получения текстовых данных.

// It is assumed that the child node is one. 
org.w3c.dom.Node nd = propertyValue.get(0).getFirstChild();
while(true) {
    if (nd.hasChildNodes()) {
        nd = nd.getFirstChild();
    } else {
        System.out.println(nd.getNodeValue()); // this is text data
        break;
    }
}
1 голос
/ 25 февраля 2011

Для этого варианта использования я бы создал XSLT, который будет преобразовывать XML-документ. Затем, используя API-интерфейсы javax.xml.transform. *, Преобразуйте XML в JAXBResult, чтобы демонтировать объект:

import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.util.JAXBResult;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        TransformerFactory tf = TransformerFactory.newInstance();

        File xsltFile = new File("transform.xsl");
        StreamSource xsltSource = new StreamSource(xsltFile);
        Transformer transformer = tf.newTransformer(xsltSource);

        File xml = new File("input.xml");
        StreamSource xmlSource = new StreamSource(xml);

        JAXBContext jc = JAXBContext.newInstance(Filter.class);
        JAXBResult jaxbResult = new JAXBResult(jc);

        transformer.transform(xmlSource, jaxbResult);

        Filter filter = (Filter) jaxbResult.getResult();
    }

}

transform.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node() | @*">
        <xsl:copy>
            <xsl:apply-templates select="node() | @*" />
        </xsl:copy>
    </xsl:template>
    <xsl:template match="propertyValue"> <xsl:value-of select="descendents"/>
       <xsl:element name="propertyValue">
           <xsl:value-of select="node()"/>
       </xsl:element>
    </xsl:template>
</xsl:stylesheet>
0 голосов
/ 25 февраля 2011

AFAIK Работа JAXB над XML-схемой для демаршаллинга XML в объект Java. Поэтому, если схема определяет элемент как простой элемент, он может содержать только текст. Если вам нужно хранить XML как простой текст. Возможно, вам придется избежать его с помощью конструкции CDATA. Попробуйте приложить то же, что показано ниже, после разбивки вы получите XML как есть.

<filter>
  <propertyType>
    <propertyName>prop1</propertyName>
    <propertyValue>val1</propertyValue>
  </propertyType>
  <propertyType>
    <propertyName>prop2</propertyName>
    <propertyValue><![CDATA[<nodeA><nodeB>valB</nodeB></nodeA>]]></propertyValue>
  </propertyType>
</filter>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...