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;

}

演示

我们将使用XMLStreamReader. 在此基础上,XMLStreamReader我们将创建一个StreamReaderDelegate报告任何以元素开头author的元素,称为author.

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 回答