Java XML XSLT生成HTML报告

时间:2016-02-28 22:55:10

标签: java html xml xslt jaxb

编辑现在我知道为什么人们使用字符串构建器,使用JAXB是一件痛苦而且非常耗时的事情,至少对我来说这是因为我有一个非常复杂的XML来生成。感谢帮助:)

我有一个收集用户数据的java应用程序。

我还创建了一个模板XSL。现在我被卡住了。我下一步要做什么?我应该使用java代码来创建XML吗?如果是这样,我创建了什么样的XML,我需要在最后严格要求我的HTML。很抱歉,如果这是重复的,我无法找到任何内容,而且我对XML完全陌生。还有一个问题是,这是xml的有效语法:

StringBuilder sb = new StringBuilder(500);
sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
sb.append("<report version=\"").append(reportVersion).append("\" generated=\"").append(scanVersion).append("\">\r\n");
sb.append("</report >");

输出为

<?xml version="1.0" encoding="UTF-8"?>
<report version="alpha" generated="1">
</report >

我现在如何使用java获取版本并生成?

我也明白有xslt 1.0和2.0,我应该选哪一个?

修改

我正在玩JAXB并获得了以下两个课程。

import java.util.ArrayList;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Report
{
    String              title;
    String              reportBy;
    String              reportFor;
    String              scanDate;
    String              scanVersion;
    String              reportDate;
    String              reportVersion;
    String              desc;
    ArrayList<String>   alertSeverity;
    ArrayList<String>   alertDetails;

    public String getTitle()
    {
        return title;
    }

    @XmlElement
    public void setTitle(String title)
    {
        this.title = title;
    }

    public String getBy()
    {
        return reportBy;
    }

    @XmlElement
    public void setBy(String reportBy)
    {
        this.reportBy = reportBy;
    }

    public String getFor()
    {
        return reportFor;
    }

    @XmlElement
    public void setFor(String reportFor)
    {
        this.reportFor = reportFor;
    }

    public String getScanDate()
    {
        return scanDate;
    }

    @XmlElement
    public void setScanDate(String scanDate)
    {
        this.scanDate = scanDate;
    }

    public String getScanVersion()
    {
        return scanVersion;
    }

    @XmlElement
    public void setScanVersion(String scanVersion)
    {
        this.scanVersion = scanVersion;
    }

    public String getReportDate()
    {
        return reportDate;
    }

    @XmlElement
    public void setReportDate(String reportDate)
    {
        this.reportDate = reportDate;
    }

    public String getReportVersion()
    {
        return reportVersion;
    }

    @XmlElement
    public void setReportVersion(String reportVersion)
    {
        this.reportVersion = reportVersion;
    }


    public String getDesc()
    {
        return reportVersion;
    }

    @XmlElement
    public void setDesc(String desc)
    {
        this.desc = desc;
    }
}

和主要:

import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class JAXBExample {
    public static void main(String[] args) {
        DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        Date date = new Date();

        Report report = new Report();
        report.setTitle("my custom title");
        report.setBy("hans");
        report.setFor("pepe");
        report.setScanDate(dateFormat.format(date));
        report.setScanVersion("orignal version");
        report.setReportDate(dateFormat.format(date));
        report.setReportVersion("version is alpha");
        report.setDesc("some random desc");

      try {

        File file = new File("C:\\Users\\testuser\\Desktop\\file.xml");


        JAXBContext jaxbContext = JAXBContext.newInstance(Report.class);
        Marshaller jaxbMarshaller = jaxbContext.createMarshaller();

        // output pretty printed
        jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        jaxbMarshaller.marshal(report, file);
        jaxbMarshaller.marshal(report, System.out);

          } catch (JAXBException e) {
        e.printStackTrace();
          }

    }
}

我只是不知道如何处理我需要循环添加元素的ArrayList等。

目前的输出是:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<report>
    <by>hans</by>
    <desc>version is alpha</desc>
    <for>pepe</for>
    <reportDate>2016/02/28 18:36:33</reportDate>
    <reportVersion>version is alpha</reportVersion>
    <scanDate>2016/02/28 18:36:33</scanDate>
    <scanVersion>orignal version</scanVersion>
    <title>my custom title</title>
</report>

现在我有两个应该进入此报告的数组,不知道如何处理它们。不仅如此,如果用户没有选择要进入的项目,那么它不应该这样做。因此,xml永远不会相同,一个属性可能不存在,有时也可能存在。这有意义吗?

编辑2:我需要的是这样的东西

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<report>
    <by>hans</by>
    <desc>version is alpha</desc>
    <for>pepe</for>
    <reportDate>2016/02/28 18:36:33</reportDate>
    <reportVersion>version is alpha</reportVersion>
    <scanDate>2016/02/28 18:36:33</scanDate>
    <scanVersion>orignal version</scanVersion>
    <title>my custom title</title>
    <site host="1" name="1" port="80" ssl="true">
        <items>
            <item>
                <name>item 1</name>
                <id>1</id>
            </item>
            <item>
                <name>item 2</name>
                <id>1</id>
            </item>
        </items>
    </site>
    <site host="2" name="2" port="80" ssl="true">
        <items>
            <item>
                <name>item 1</name>
                <id>1</id>
            </item>
            <item>
                <name>item 2</name>
                <id>1</id>
            </item>
        </items>
    </site>
</report>

所有这些都包含在ArrayList我如何使用JAXB创建这个xml?任何输入将不胜感激:)

1 个答案:

答案 0 :(得分:1)

第1步

创建一个XSD,表示XML中所需的结构。如果您不熟悉XSD,我建议您阅读this tutorial

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
    elementFormDefault="qualified">

    <xs:element name="report">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="1" name="by" type="xs:string" />
                <xs:element minOccurs="0" maxOccurs="1" name="desc" type="xs:string" />
                <xs:element minOccurs="0" maxOccurs="1" name="for" type="xs:string" />
                <xs:element minOccurs="0" maxOccurs="1" name="reportDate"
                    type="xs:dateTime" />
                <xs:element minOccurs="0" maxOccurs="1" name="reportVersion"
                    type="xs:string" />
                <xs:element minOccurs="0" maxOccurs="1" name="scanDate"
                    type="xs:dateTime" />
                <xs:element minOccurs="0" maxOccurs="1" name="scanVersion"
                    type="xs:string" />
                <xs:element minOccurs="0" maxOccurs="1" name="title"
                    type="xs:string" />
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="site" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="site">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="1" maxOccurs="1" ref="items" />
            </xs:sequence>
            <xs:attribute use="required" name="host" type="xs:string" />
            <xs:attribute use="required" name="name" type="xs:string" />
            <xs:attribute use="required" name="port" type="xs:string" />
            <xs:attribute use="required" name="ssl" type="xs:string" />
        </xs:complexType>
    </xs:element>

    <xs:element name="items">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="0" maxOccurs="unbounded" ref="item" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

    <xs:element name="item">
        <xs:complexType>
            <xs:sequence>
                <xs:element minOccurs="1" maxOccurs="1" name="name" type="xs:string" />
                <xs:element minOccurs="1" maxOccurs="1" name="id" type="xs:string" />
            </xs:sequence>
        </xs:complexType>
    </xs:element>

</xs:schema>

注1:类型xs:dateTime仅允许在ISO 8601格式化的日期时间。 Source W3C。如果你真的想要一个自定义日期时间格式,你将不得不根据字符串编写自己的模式(因此失去了日期验证的全部功能)。

注意2:正如您所注意到的,xs:element有一个minOccursmaxOccurs可以调整,如果你知道一个元素是强制性的。

第2步

您可以使用工具XJC(与Java捆绑在一起)自动生成相应的Java类。 JAXB可以直接使用这些类将数据序列化为所需的XML格式。

以下命令应该可以解决问题:

/path/to/jdk/bin/xjc -d /path/to/output/folder -p your.package.name /path/to/report.xsd

应生成以下类(样本)

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "name",
    "id"
})
@XmlRootElement(name = "item")
public class Item {

    @XmlElement(required = true)
    protected String name;
    @XmlElement(required = true)
    protected String id;

    public String getName() {
        return name;
    }

    public void setName(String value) {
        this.name = value;
    }

    public String getId() {
        return id;
    }

    public void setId(String value) {
        this.id = value;
    }
}

注意:生成的类是简单的POJO,我不鼓励直接使用(只有JAXB可以使用)。如果您已经根据业务构建了Report类,则可以创建一些XmlAdapter来映射业务对象和JAXB-POJO。

第3步

使用报告数据填写这些对象:

Item i1 = new Item();
i1.setName("item 1");
i1.setId("1");

Item i2 = new Item();
i2.setName("item 2");
i2.setId("2");

Items items = new Items();
items.getItem().addAll(Arrays.asList(i1, i2));

Site s1 = new Site();
s1.setHost("1");
s1.setName("1");
s1.setPort("80");
s1.setSsl("true");
s1.setItems(items);

Site s2 = new Site();
s2.setHost("2");
s2.setName("2");
s2.setPort("80");
s2.setSsl("true");
s2.setItems(items);

Report r = new Report();
r.setBy("hans");
r.setDesc("version is alpha");
r.setFor("pepe");
r.setReportDate(DatatypeFactory.newInstance().newXMLGregorianCalendar("2016-02-28T18:36:33"));
r.setReportVersion("version is alpha");
r.setScanDate(DatatypeFactory.newInstance().newXMLGregorianCalendar("2016-02-28T18:36:33"));
r.setScanVersion("original version");
r.setTitle("my custom title");
r.getSite().addAll(Arrays.asList(s1, s2));

注意:如果你有xmlAdapters,这一步就变得不那么乏味了。

第4步

将它们保存为XML

JAXBContext jaxbContext = JAXBContext.newInstance(Report.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
jaxbMarshaller.marshal(r, new File("report.xml"));

注意:report.xml将完全采用您需要的格式。

第5步

在HTML中转换XML

StreamResult result = new StreamResult(new File("output.html"));
StreamSource source = new StreamSource(new File("report.xml"));
StreamSource xslt = new StreamSource(new File("transform.xslt"));

Transformer transformer = TransformerFactory.newInstance().newTransformer(xslt);

transformer.transform(source, result);