使用 BIRT 解析 XML

Parse XML with BIRT

我是 BIRT 的新手,XML 但正在尝试解决性能问题。现在我们有一个报告使用一个大的 XML 文件作为数据源,加载时间很长。所以我一直在探索不同的选择。我发现您可以使用脚本数据源并使用 java 来解析 XML。

我的问题是,即使 XML 文件中有信息,它也会将某些行留空。

我有一个测试 XML 文件,如下所示:

<?xml version="1.0"?>
<library>
    <book category="COOKING">
        <title lang="en">Everyday Italian</title>
        <author name="Giada De Laurentiis" country="it"/>
        <year>2005</year>
        <info>asdfghjkl</info>
    </book>    
    <book category="CHILDREN">
        <title lang="en">Harry Potter</title>
        <author name="J K. Rowling" country="uk" />
        <year>2005</year>
        <info>asdfghjkl</info>
    </book>    
    <book category="WEB">
        <title lang="en">XQuery Kick Start</title>

        <author name="James McGovern" country="us" />
        <author name="Per Bothner" country="us" />
        <info>asdfghjkl</info>
    </book>    
    <book category="WEB">
        <title lang="en">Learning XML</title>
        <author name="Erik T. Ray" country="us" />
        <year>2003</year>
        <info>asdfghjkl</info>
    </book>
</library>

在我打开的数据集中我有

importPackage(javax.xml.parsers);
importPackage(javax.xml.xpath);
importPackage(org.w3c.dom);
importPackage(org.xml.sax);

var factory = DocumentBuilderFactory.newInstance();
var builder = null;
 doc = null;
var expr = null;

factory.setNamespaceAware(true);

builder = factory.newDocumentBuilder();
doc = builder.parse(params["FileName"].value);
doc.getDocumentElement().normalize();

// create an XPathFactory
var xFactory = XPathFactory.newInstance();

// create an XPath object
 xpath = xFactory.newXPath();

// compile the XPath expression
expr = xpath.compile("/library/*");
// run the query and get a nodeset
var result = expr.evaluate(doc, XPathConstants.NODESET);

//initialize object variables to be used in the fetch method
nodes = result;

x = 0;
y = 0;

cnt = nodes.getLength();

正在获取我有

var lboolAllowed = false;

if (x < cnt)
{

    var nodeList = nodes.item(x).getChildNodes();
    var nodeListLength = nodes.item(x).getChildNodes().getLength();
    for(var i=0; i<nodeListLength; i++)
    {
        var nodeName = nodeList.item(i).getNodeName();
        var nodeText = nodeList.item(i).getTextContent();
        if(nodeName == "category")
        {
            row["category"] = nodeText;
        }
        if(nodeName == "year")
        {
            row["year"] = nodeText;
        }
        else if(nodeName == "info")
        {
            row["info"] = nodeText;
        }
        else if(nodeName == "title")
        {
        row["title"] = nodeText;
        }
        else if(nodeName == "author")
        {
        row["author"] = nodeText;
        }
        else if(nodeName == "country")
        {
        row["country"] = nodeText;
        }

        y++
    }   
    x++;
    y=0;
    return (true);

    }
return (false);

然后我有一个名为 FileName 的报告参数,它指向 XML 文件所在的位置。 出现空白的行是类别、作者和国家/地区。我使用的是 3.2.23 版。 如果有帮助,这里是报告的 XML 来源。

<?xml version="1.0" encoding="UTF-8"?>
<report xmlns="http://www.eclipse.org/birt/2005/design" version="3.2.23" id="1">
    <property name="createdBy">Eclipse BIRT Designer Version 4.6.0.v201606072122</property>
    <property name="units">in</property>
    <property name="iconFile">/templates/blank_report.gif</property>
    <property name="bidiLayoutOrientation">ltr</property>
    <property name="imageDPI">120</property>
    <parameters>
        <scalar-parameter name="FileName" id="11">
            <property name="hidden">true</property>
            <property name="valueType">static</property>
            <property name="dataType">string</property>
            <property name="distinct">true</property>
            <simple-property-list name="defaultValue">
                <value type="constant">C:\Users22335\Desktop\Workspace\test\new207.xml</value>
            </simple-property-list>
            <list-property name="selectionList"/>
            <property name="paramType">simple</property>
            <property name="controlType">text-box</property>
            <structure name="format">
                <property name="category">Unformatted</property>
            </structure>
        </scalar-parameter>
    </parameters>
    <data-sources>
        <script-data-source name="Data Source" id="9"/>
    </data-sources>
    <data-sets>
        <script-data-set name="Data Set" id="12">
            <list-property name="resultSetHints">
                <structure>
                    <property name="position">1</property>
                    <property name="name">year</property>
                    <property name="dataType">integer</property>
                </structure>
                <structure>
                    <property name="position">2</property>
                    <property name="name">info</property>
                    <property name="dataType">string</property>
                </structure>
                <structure>
                    <property name="position">3</property>
                    <property name="name">category</property>
                    <property name="dataType">string</property>
                </structure>
                <structure>
                    <property name="position">4</property>
                    <property name="name">title</property>
                    <property name="dataType">string</property>
                </structure>
                <structure>
                    <property name="position">5</property>
                    <property name="name">author</property>
                    <property name="dataType">string</property>
                </structure>
                <structure>
                    <property name="position">6</property>
                    <property name="name">country</property>
                    <property name="dataType">string</property>
                </structure>
            </list-property>
            <list-property name="columnHints">
                <structure>
                    <property name="columnName">year</property>
                    <text-property name="displayName">year</text-property>
                </structure>
                <structure>
                    <property name="columnName">info</property>
                    <text-property name="displayName">info</text-property>
                </structure>
                <structure>
                    <property name="columnName">category</property>
                    <text-property name="displayName">category</text-property>
                </structure>
                <structure>
                    <property name="columnName">title</property>
                    <text-property name="displayName">title</text-property>
                </structure>
                <structure>
                    <property name="columnName">author</property>
                    <text-property name="displayName">author</text-property>
                </structure>
                <structure>
                    <property name="columnName">country</property>
                    <text-property name="displayName">country</text-property>
                </structure>
            </list-property>
            <structure name="cachedMetaData">
                <list-property name="resultSet">
                    <structure>
                        <property name="position">1</property>
                        <property name="name">year</property>
                        <property name="dataType">integer</property>
                    </structure>
                    <structure>
                        <property name="position">2</property>
                        <property name="name">info</property>
                        <property name="dataType">string</property>
                    </structure>
                    <structure>
                        <property name="position">3</property>
                        <property name="name">category</property>
                        <property name="dataType">string</property>
                    </structure>
                    <structure>
                        <property name="position">4</property>
                        <property name="name">title</property>
                        <property name="dataType">string</property>
                    </structure>
                    <structure>
                        <property name="position">5</property>
                        <property name="name">author</property>
                        <property name="dataType">string</property>
                    </structure>
                    <structure>
                        <property name="position">6</property>
                        <property name="name">country</property>
                        <property name="dataType">string</property>
                    </structure>
                </list-property>
            </structure>
            <property name="dataSource">Data Source</property>
            <method name="open"><![CDATA[importPackage(javax.xml.parsers);
importPackage(javax.xml.xpath);
importPackage(org.w3c.dom);
importPackage(org.xml.sax);

var factory = DocumentBuilderFactory.newInstance();
var builder = null;
 doc = null;
var expr = null;

factory.setNamespaceAware(true);

builder = factory.newDocumentBuilder();
//doc = builder.parse("C:\Users22335\Desktop\Workspace\test\new207.xml");
doc = builder.parse(params["FileName"].value);
doc.getDocumentElement().normalize();

// create an XPathFactory
var xFactory = XPathFactory.newInstance();

// create an XPath object
 xpath = xFactory.newXPath();

// compile the XPath expression
expr = xpath.compile("/library/*");
// run the query and get a nodeset
var result = expr.evaluate(doc, XPathConstants.NODESET);

//initialize object variables to be used in the fetch method
nodes = result;

x = 0;
y = 0;

cnt = nodes.getLength();
]]></method>
            <method name="fetch"><![CDATA[var lboolAllowed = false;

if (x < cnt)
{

    var nodeList = nodes.item(x).getChildNodes();
    var nodeListLength = nodes.item(x).getChildNodes().getLength();
    for(var i=0; i<nodeListLength; i++)
    {
        var nodeName = nodeList.item(i).getNodeName();
        var nodeText = nodeList.item(i).getTextContent();
        if(nodeName == "@category")
        {
            row["category"] = nodeText;
        }
        if(nodeName == "year")
        {
            row["year"] = nodeText;
        }
        else if(nodeName == "info")
        {
            row["info"] = nodeText;
        }
        else if(nodeName == "//title")
        {
        row["title"] = nodeText;
        }
        else if(nodeName == "//author")
        {
        row["author"] = nodeText;
        }
        else if(nodeName == "//country")
        {
        row["country"] = nodeText;
        }

        y++
    }   
    x++;
    y=0;
    return (true);

    }
return (false);]]></method>
            <method name="close"><![CDATA[factory = null;
builder = null;
doc = null;
expr = null;
builder = null;
xFactory = null;

// create an XPath object
 xpath = null;

result = null;

//initialize object variables to be used in the fetch method
nodes = null;

x = 0;
y = 0;

cnt = null;]]></method>
        </script-data-set>
    </data-sets>
    <page-setup>
        <simple-master-page name="Simple MasterPage" id="2">
            <page-footer>
                <text id="3">
                    <property name="contentType">html</property>
                    <text-property name="content"><![CDATA[<value-of>new Date()</value-of>]]></text-property>
                </text>
            </page-footer>
        </simple-master-page>
    </page-setup>
    <body>
        <table id="356">
            <property name="dataSet">Data Set</property>
            <list-property name="boundDataColumns">
                <structure>
                    <property name="name">year</property>
                    <text-property name="displayName">year</text-property>
                    <expression name="expression" type="javascript">dataSetRow["year"]</expression>
                    <property name="dataType">integer</property>
                </structure>
                <structure>
                    <property name="name">info</property>
                    <text-property name="displayName">info</text-property>
                    <expression name="expression" type="javascript">dataSetRow["info"]</expression>
                    <property name="dataType">string</property>
                </structure>
                <structure>
                    <property name="name">category</property>
                    <text-property name="displayName">category</text-property>
                    <expression name="expression" type="javascript">dataSetRow["category"]</expression>
                    <property name="dataType">string</property>
                </structure>
                <structure>
                    <property name="name">title</property>
                    <text-property name="displayName">title</text-property>
                    <expression name="expression" type="javascript">dataSetRow["title"]</expression>
                    <property name="dataType">string</property>
                </structure>
                <structure>
                    <property name="name">author</property>
                    <text-property name="displayName">author</text-property>
                    <expression name="expression" type="javascript">dataSetRow["author"]</expression>
                    <property name="dataType">string</property>
                </structure>
                <structure>
                    <property name="name">country</property>
                    <text-property name="displayName">country</text-property>
                    <expression name="expression" type="javascript">dataSetRow["country"]</expression>
                    <property name="dataType">string</property>
                </structure>
            </list-property>
            <column id="390"/>
            <column id="391"/>
            <column id="392"/>
            <column id="393"/>
            <column id="394"/>
            <column id="395"/>
            <header>
                <row id="357">
                    <cell id="358">
                        <label id="359">
                            <text-property name="text">year</text-property>
                        </label>
                    </cell>
                    <cell id="360">
                        <label id="361">
                            <text-property name="text">info</text-property>
                        </label>
                    </cell>
                    <cell id="362">
                        <label id="363">
                            <text-property name="text">category</text-property>
                        </label>
                    </cell>
                    <cell id="364">
                        <label id="365">
                            <text-property name="text">title</text-property>
                        </label>
                    </cell>
                    <cell id="366">
                        <label id="367">
                            <text-property name="text">author</text-property>
                        </label>
                    </cell>
                    <cell id="368">
                        <label id="369">
                            <text-property name="text">country</text-property>
                        </label>
                    </cell>
                </row>
            </header>
            <detail>
                <row id="370">
                    <cell id="371">
                        <data id="372">
                            <property name="resultSetColumn">year</property>
                        </data>
                    </cell>
                    <cell id="373">
                        <data id="374">
                            <property name="resultSetColumn">info</property>
                        </data>
                    </cell>
                    <cell id="375">
                        <data id="376">
                            <property name="resultSetColumn">category</property>
                        </data>
                    </cell>
                    <cell id="377">
                        <data id="378">
                            <property name="resultSetColumn">title</property>
                        </data>
                    </cell>
                    <cell id="379">
                        <data id="380">
                            <property name="resultSetColumn">author</property>
                        </data>
                    </cell>
                    <cell id="381">
                        <data id="382">
                            <property name="resultSetColumn">country</property>
                        </data>
                    </cell>
                </row>
            </detail>
            <footer>
                <row id="383">
                    <cell id="384"/>
                    <cell id="385"/>
                    <cell id="386"/>
                    <cell id="387"/>
                    <cell id="388"/>
                    <cell id="389"/>
                </row>
            </footer>
        </table>
    </body>
</report>

这是一个 XML/DOM 相关问题:nodeName 没有 @// 作为前缀(即 XPath 内容),只有元素或属性名称, 所以不是 @category 而只是 category, 在

中删除它们
   if(nodeName == "@category")

   else if(nodeName == "//author")
    {
    row["author"] = nodeText;
    }
    else if(nodeName == "//country")
    {
    row["country"] = nodeText;
    }

DOM Node javadoc 中的 table 显示了 Node.getNodeName()

返回的内容

另外你查询category/author/country的节点是错误的,见:

var book =  nodes.item(x);
var nodeList = book.getChildNodes();
var nodeListLength = nodeList.getLength();
row["category"] = book.getAttribute("category");
for(int i=0; i<nodeListLength; i++)
{
    var child = nodeList.item(i);
    var nodeName = child.getNodeName();
    var nodeText = child.getTextContent();
    if(nodeName == "year")
    {
        row["year"] = nodeText);
    }
    else if(nodeName == "info")
    {
        row["info"] = nodeText);
    }
    else if(nodeName == "title")
    {
        row["title"] = nodeText);
    }
    else if(nodeName == "author")
    {
        row["author"] =  child.getAttribute("name");
        row["country"] = child.getAttribute("country");
    }     

注:作者其实是一个列表