在JSF中读写XML文件 [英] Reading and writing a XML file in JSF

查看:65
本文介绍了在JSF中读写XML文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我没有在网上找到有关如何在JSF中读取/写入XML文档的任何信息.我知道使用 XALAN 的JSP和JSTL.例如,

以下XML文件是在/WEB-INF下定义的.

<?xml version="1.0" encoding="UTF-8"?>

<fruits>
    <fruit>
        <name>Orange</name>
        <price>10</price>
    </fruit>

    <fruit>
        <name>Banana</name>
        <price>20</price>
    </fruit>

    <fruit>
        <name>Apple</name>
        <price>30</price>
    </fruit>
</fruits>

可以像下面这样在JSP中阅读该文档.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>

<c:import var="items" url="/WEB-INF/TextXML.xml"/>
<x:parse var="fruits" doc="${items}"/>

<table rules="all" border="1">
    <tr>
        <th>index</th>
        <th>Fruit Name</th>
        <th>Price</th>
    </tr>

    <x:forEach var="item" select="$fruits/fruits/fruit" varStatus="loop">
        <tr>
            <td><c:out value="${loop.index+1}"/></td>
            <td><x:out select="$item/name" /></td>
            <td><x:out select="$item/price" /></td>
        </tr>
    </x:forEach>
</table>

这将用三列填充一个HTML表.

在JSF中如何通过使用JAXB或其他方式实现相同的目的?

解决方案

您确实可以使用 JAXB 为此.

让我们假设您已经有一个表示<fruit>的javabean.您甚至可以为此重用现有的JPA实体.

 public class Fruit {

    private String name;
    private BigDecimal price;

    // Add/generate getters+setters.
}
 

(请注意,javabean类和属性名称必须与XML元素名称<fruit><name><price>完全匹配,否则在这两个名称上都需要@XmlElement(name="actualXmlElementName"))

现在,创建另一个代表<fruits>的javabean,纯粹用于JAXB(它需要一个代表XML根元素的@XmlRootElement类,即使XML文档基本上只包含一个实体列表).

 @XmlRootElement
public class Fruits { // Classname must match <fruits>, otherwise set it as @XmlRootElement(name="fruits")

    @XmlElement(name="fruit") // Name must thus match <fruit>. We could also make the property name "fruit" so that we can omit @XmlElement, but a getFruit() method returning a list of fruits isn't self-documenting.
    private List<Fruit> list;

    public Fruits() {
        // Keep default c'tor alive.
    }

    public Fruits(List<Fruit> list) {
        this.list = list;
    }

    public List<Fruit> getList() { 
        return list;
    }

}
 

关于读/写,您可以在JSF中完美地从/WEB-INF读取,如下所示:

 InputStream input = externalContext.getResourceAsStream("/WEB-INF/fruits.xml");
 

但是写作是另外一个故事.您不应该将文件写入部署空间.显然不打算将其用作永久存储位置,因为显而易见的原因是,每当您重新部署WAR时,所有更改都会丢失.您需要将其写入部署空间之外的固定路径.在下面的示例中,我假设文件已移动到服务器磁盘文件系统上的/var/webapp/fruits.xml.

因此,您可以使用JAXB来在托管bean中读取和写入XML文件,如下所示:

 @Named
@RequestScoped
public class Bean {

    private File file = new File("/var/webapp/fruits.xml");
    private JAXBContext jaxb; // Can be application scoped. It's thread safe.
    private List<Fruit> fruits;

    @PostConstruct
    public void init() throws JAXBException, IOException {
        jaxb = JAXBContext.newInstance(Fruits.class);
        fruits = ((Fruits) jaxb.createUnmarshaller().unmarshal(file)).getList();
    }

    public void save() throws JAXBException {
        jaxb.createMarshaller().marshal(new Fruits(fruits), file);
    }

    public List<Fruit> getFruits() { 
        return fruits;
    }

}
 

您可以按通常的方式显示它以便用JSF <h:dataTable>进行编辑.

<h:dataTable value="#{bean.fruits}" var="fruit">
    <h:column><h:inputText value="#{fruit.name}" /></h:column>
    <h:column><h:inputText value="#{fruit.price}" /></h:column>
</h:dataTable>

I found nothing online about how to read/write an XML document in JSF. I know something in JSP along with JSTL using XALAN. For example,

The following XML file is defined under /WEB-INF.

<?xml version="1.0" encoding="UTF-8"?>

<fruits>
    <fruit>
        <name>Orange</name>
        <price>10</price>
    </fruit>

    <fruit>
        <name>Banana</name>
        <price>20</price>
    </fruit>

    <fruit>
        <name>Apple</name>
        <price>30</price>
    </fruit>
</fruits>

This document can be read in JSP like the following.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>

<c:import var="items" url="/WEB-INF/TextXML.xml"/>
<x:parse var="fruits" doc="${items}"/>

<table rules="all" border="1">
    <tr>
        <th>index</th>
        <th>Fruit Name</th>
        <th>Price</th>
    </tr>

    <x:forEach var="item" select="$fruits/fruits/fruit" varStatus="loop">
        <tr>
            <td><c:out value="${loop.index+1}"/></td>
            <td><x:out select="$item/name" /></td>
            <td><x:out select="$item/price" /></td>
        </tr>
    </x:forEach>
</table>

This would populate an HTML table with three columns.

How can the same thing be achieved in JSF, maybe by using JAXB or something else?

解决方案

You can indeed use JAXB for this.

Let's assume that you already have a javabean representing <fruit>. You can even reuse an existing JPA entity for this.

public class Fruit {

    private String name;
    private BigDecimal price;

    // Add/generate getters+setters.
}

(note that javabean class and property names must exactly match XML element names <fruit>, <name> and <price>, otherwise you need a @XmlElement(name="actualXmlElementName") on either of those)

Now, create another javabean representing <fruits>, purely for usage in JAXB (it namely requires a @XmlRootElement class representing the XML root element, even though the XML document basically only contains a list of entities).

@XmlRootElement
public class Fruits { // Classname must match <fruits>, otherwise set it as @XmlRootElement(name="fruits")

    @XmlElement(name="fruit") // Name must thus match <fruit>. We could also make the property name "fruit" so that we can omit @XmlElement, but a getFruit() method returning a list of fruits isn't self-documenting.
    private List<Fruit> list;

    public Fruits() {
        // Keep default c'tor alive.
    }

    public Fruits(List<Fruit> list) {
        this.list = list;
    }

    public List<Fruit> getList() { 
        return list;
    }

}

As to reading/writing, you can in JSF perfectly read from /WEB-INF as follows:

InputStream input = externalContext.getResourceAsStream("/WEB-INF/fruits.xml");

But writing is a story apart. You aren't supposed to write files to deployment space. It isn't intented as permanent storage location for the obvious reason that all changes will get lost whenever you redeploy the WAR. You need to write it to a fixed path somewhere outside the deploy space. In the below example I'll assume that the file is moved to /var/webapp/fruits.xml on the server's disk file system.

So, you can use JAXB to read and write the XML file in a managed bean as follows:

@Named
@RequestScoped
public class Bean {

    private File file = new File("/var/webapp/fruits.xml");
    private JAXBContext jaxb; // Can be application scoped. It's thread safe.
    private List<Fruit> fruits;

    @PostConstruct
    public void init() throws JAXBException, IOException {
        jaxb = JAXBContext.newInstance(Fruits.class);
        fruits = ((Fruits) jaxb.createUnmarshaller().unmarshal(file)).getList();
    }

    public void save() throws JAXBException {
        jaxb.createMarshaller().marshal(new Fruits(fruits), file);
    }

    public List<Fruit> getFruits() { 
        return fruits;
    }

}

You can display it for editing in a JSF <h:dataTable> the usual way.

<h:dataTable value="#{bean.fruits}" var="fruit">
    <h:column><h:inputText value="#{fruit.name}" /></h:column>
    <h:column><h:inputText value="#{fruit.price}" /></h:column>
</h:dataTable>

这篇关于在JSF中读写XML文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆