9

問題

次のXML構成ファイルがあるとします。

<main>
  <name>JET</name>
  <maxInstances>5</maxInstances>
  <parameters>
    <a>1</a>
    <b>
      <b1>test1</b1>
      <b2>test2</b2>
    </b>
  </parameters>
</main>

name要素とmaxInstances要素の値を抽出してから、parameters要素の内部テキスト全体を抽出する必要があります。例えば

name = "JET"
maxInstances = 5
parameters = "<a>1</a><b><b1>test1</b1><b2>test2</b2></b>"

最終的に、parametersブロックには整形式のXMLを含めることができます。

試みられた解決策

次のコードは、nameとmaxInstancesに対して機能しますが、パラメーターに対しては機能しません。

@XmlRootElement(name="main")
public class Main {

    @XmlElement(name="name", required="true")
    private String name;

    @XmlElement(name="maxInstances", required="true")
    private Integer maxInstances;

    @XmlElement(name="parameters")
    private String parameters;

}

以下のアイデアに基づいて解決策を検討してみましたが、適切なものが見つかりません。

文字列を生成するために解析できるXMLツリーを表すパラメーターオブジェクトに使用できる別のタイプはありますか?例えば

@XmlElement(name="parameters")
private XmlNodeObject parametersNode;

public String getParameters() {
    // Collapse node to single line of text
    return innerText;
}

または、別の種類の注釈を使用する必要がありますか?

@XmlSpecialAnnotation(...)
@XmlElement(name="parameters")
private String parameters;

別のスタイルのパーサーに切り替える必要がありますか?2つのスタイルのパーサーを使用するのは良い/悪い考えですか?

4

2 に答える 2

12

bmarguliesで説明されているよう@XmlAnyElementに注釈を使用できます。質問のオブジェクトモデルにマップするには、を活用できます。DOMHandler

主要

import javax.xml.bind.annotation.*;

@XmlRootElement(name="main")
@XmlAccessorType(XmlAccessType.FIELD)
public class Main {

    private String name;

    private Integer maxInstances;

    @XmlAnyElement(value=ParameterHandler.class)
    private String parameters;

}

ParameterHandler

import java.io.*;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.annotation.DomHandler;
import javax.xml.transform.Source;
import javax.xml.transform.stream.*;

public class ParameterHandler implements DomHandler<String, StreamResult> {

    private static final String PARAMETERS_START_TAG = "<parameters>";
    private static final String PARAMETERS_END_TAG = "</parameters>";
    private StringWriter xmlWriter = new StringWriter(); 

    public StreamResult createUnmarshaller(ValidationEventHandler errorHandler) {
        return new StreamResult(xmlWriter);
    }

    public String getElement(StreamResult rt) {
        String xml = rt.getWriter().toString();
        int beginIndex = xml.indexOf(PARAMETERS_START_TAG) + PARAMETERS_START_TAG.length();
        int endIndex = xml.indexOf(PARAMETERS_END_TAG);
        return xml.substring(beginIndex, endIndex);
    }

    public Source marshal(String n, ValidationEventHandler errorHandler) {
        try {
            String xml = PARAMETERS_START_TAG + n.trim() + PARAMETERS_END_TAG;
            StringReader xmlReader = new StringReader(xml);
            return new StreamSource(xmlReader);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

}

デモ

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception  {
        JAXBContext jc = JAXBContext.newInstance(Main.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Main main = (Main) unmarshaller.unmarshal(new File("input.xml"));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(main, System.out);
    }

}
于 2011-04-05T14:38:51.570 に答える
6

最も近い方法は、変数を。と宣言することにより、「パラメーター」をDOMツリーにマップすることorg.w3c.dom.Nodeです。(実際には、JAXBElementを宣言します)。

詳細については、http://jaxb.java.net/guide/Avoid_strong_databinding.htmlを参照してください。これにより、スキーマファーストの処方箋が得られます。xsd2javaを介してそのスキーマを実行し、出力を確認することで、Javaから開始する方法を確認できます。

文字列を取得するには、DOMからシリアル化する必要があります。

または、さらに具体的には:

このページでは、xsd:anyの処理について説明しています。

  @XmlAnyElement
  public List<Element> getParameters();

ElementDOMインターフェイスはどこにありますか。

于 2011-04-04T11:26:49.013 に答える