3

現在、XStream を使用して XML ファイルを解析していますが、必要な処理を行うことができません。この問題を解決できるものなら何でも、必要に応じて別のライブラリに変更します!

基本的に、次のような XML フィードを解析しようとしています。

<product>
  <title>Transformers Best of Grimlock</title>
  <author1>Bob Budiansky</author1>
  <author2>Simon Furman</author2>
</product>

私は次のようなモデルに解析しようとしています:

public class Product extends Model {

  public String title;

  public List<String> authors;

}

タイトルは美しく機能しますが、著者の解析に苦労しています。残念ながら、次のような「より適切な」形式で XML フィードを取得することはできません。

...
<authors>
  <author>Bob Budiansky</author>
  <author>Simon Furman</author>
</authors>
...

「author1」、「author2」などをリストに解析するためにできることはありますか?

私は XStream に非常に慣れていない (そして JAXB をまったく使用したことがない!) ので、カスタム バインダーなどを作成する必要がある場合は、どこから始めればよいかについてのポインターが必要になることを覚えておいてください。

読んでくれてありがとう、正気を保つ可能性のある解決策を楽しみにしています! :)


編集: XStream に縛られていないことを示すために投稿を更新しました。これに対する答えを見つけるのに本当に苦労しています - おそらく私は何を検索すればよいのかわからないだけです...

4

2 に答える 2

3

次のアプローチは、 StAX からアンマーシャリングできる任意の XML バインディング ライブラリで機能するはずXMLStreamReaderです。以下では、標準の JAXB (JSR-222) API を使用してデモを行います。(注: 私はEclipseLink JAXB (MOXy)のリーダーです)。

製品

プロパティが要素authorsにマップされているかのように、モデルに注釈を付けます。author

package forum11666565;

import java.util.List;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Product extends Model {

    public String title;

    @XmlElement(name = "author")
    public List<String> authors;

}

デモ

.xml を使用して XML ドキュメントを解析しますXMLStreamReader。その上で、で始まるすべての要素をという要素として報告XMLStreamReaderする を作成します。StreamReaderDelegateauthorauthor

package forum11666565;

import java.io.FileInputStream;
import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.stream.util.StreamReaderDelegate;

public class Demo {

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

        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLStreamReader xsr = xif.createXMLStreamReader(new FileInputStream("src/forum11666565/input.xml"));
        xsr = new StreamReaderDelegate(xsr) {

            @Override
            public String getLocalName() {
                String localName = super.getLocalName();
                if(localName.startsWith("author")) {
                    return "author";
                } else {
                    return localName;
                }
            }

        };

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Product product = (Product) unmarshaller.unmarshal(xsr);

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

}

入力.xml

<product>
  <title>Transformers: Best of Grimlock</title>
  <author1>Bob Budiansky</author1>
  <author2>Simon Furman</author2>
</product>

出力

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<product>
    <title>Transformers: Best of Grimlock</title>
    <author>Bob Budiansky</author>
    <author>Simon Furman</author>
</product>
于 2012-07-26T14:24:04.513 に答える
2

XStream で解析する前に、XSLT を介して初期 XML を変換できます。

XSLT スタイルシートは、必要に応じて XML を変換します。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="product">
        <xsl:element name="product">
            <xsl:for-each select="*[not(starts-with(name(.), 'author'))]">
                <xsl:copy-of select="." />
            </xsl:for-each>
            <xsl:element name="authors">
                <xsl:for-each select="*[starts-with(name(.), 'author')]">
                    <xsl:element name="author">
                        <xsl:value-of select="."/>
                    </xsl:element>
                </xsl:for-each>
            </xsl:element>
        </xsl:element>
    </xsl:template>

    <xsl:template match="*">
        <xsl:copy select=".">
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>
于 2012-07-26T14:56:12.297 に答える