Javascript 流解析 xml

Javascript stream parse xml

我有几个 xml 文件,我想在 Javascript 中过滤以填充 google 图表散点图。

问题是,我必须使用流解析,因为每个文件都非常大,超过 3.5 MB。

如何将 4MB xml 文件中的数据传递到 javascript 数组中,我可以在 运行 内存不足的情况下循环遍历

示例:

<?xml version="1.0" encoding="UTF-8"?>
<rootNode a="1">
    <parentNode b="2" c="3" d="4">
        <childNode e="5" f="7" g="7"/>
        <childNode e="2" f="9" g="4"/>
        <childNode e="11" f="7" g="3"/>
        ...
    </parentNode>
</rootNode>

var chart = [],
fIsSeven = [],
childNode = /*Each node of xml*/;

// Filter results and save data to 2D array
foreach (childNode) {
    if(f == 7) {
        fIsSeven = [e, g];
        chart.push(fIsSeven);
    }
}

...

// Use array to populate google chart
function drawChart() {
    var data = google.visualization.arrayToDataTable([
        ['e', 'g'],

        forEach (chart) {
            [e, g]
        }
    ]);

...

}

我发现从大型 xml 文件加载 google 数据 table 的最快方法是使用 xsl 将数据转换为 google's json format,然后创建数据 table 直接来自 json...


以下是来自用于加载 google...

的 cognos 报告的 XML 数据示例

XML

<metadata>
      <item name="Level 1" type="xs:string" length="38"/>
      <item name="Level 2" type="xs:string" length="302"/>
      <item name="Level 3" type="xs:string" length="302"/>
      <item name="Level 4" type="xs:string" length="302"/>
      <item name="Level 5" type="xs:string" length="302"/>
      <item name="Expenditure Group" type="xs:string" length="48"/>
      <item name="GL Number" type="xs:double" precision="2"/>
      <item name="Actual" type="xs:double" precision="2"/>
      <item name="Budget" type="xs:double" precision="2"/>
      <item name="Forecast" type="xs:double" precision="2"/>
      <item name="Category" type="xs:string" length="102"/>
</metadata>
<data>
    <row>
        <value>SBU</value>
        <value>BU</value>
        <value>Department</value>
        <value>Office</value>
        <value>Site</value>
        <value>Expense</value>
        <value>3</value>
        <value>13811.22</value>
        <value>6175</value>
        <value>13811.22</value>
        <value>Category</value>
    </row>
    <row>
        <value>SBU</value>
        <value>BU</value>
        <value>Department</value>
        <value>Office</value>
        <value>Site</value>
        <value>Expense</value>
        <value>3</value>
        <value>13811.22</value>
        <value>6175</value>
        <value>13811.22</value>
        <value>Category</value>
    </row>
    ...

以下是用于将 XML 转换为 google 的 JSON 格式的 XSL...

XSL

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns="http://tempuri.org/"
  xmlns:cog="http://developer.cognos.com/schemas/xmldata/1/"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:output method="text" omit-xml-declaration="yes" indent="no" />
  <xsl:template match="/">
    {
      "cols": [
        {"label": "SBU", "type": "string"},
        {"label": "BU", "type": "string"},
        {"label": "Department", "type": "string"},
        {"label": "Office", "type": "string"},
        {"label": "Site", "type": "string"},
        {"label": "Expenditure Group", "type": "string"},
        {"label": "Period", "type": "number", "p": {"format": "d2"}},
        {"label": "Actual", "type": "number", "p": {"format": "n2"}},
        {"label": "Budget", "type": "number", "p": {"format": "n2"}},
        {"label": "Forecast", "type": "number", "p": {"format": "n2"}},
        {"label": "O&amp;M Category", "type": "string"}
      ],
      "rows": [
      <xsl:for-each select="//cog:row">
        {"c":[
          {"v": "<xsl:value-of select="cog:value[1]" />"},
          {"v": "<xsl:value-of select="cog:value[2]" />"},
          {"v": "<xsl:value-of select="cog:value[3]" />"},
          {"v": "<xsl:value-of select="cog:value[4]" />"},
          {"v": "<xsl:value-of select="cog:value[5]" />"},
          {"v": "<xsl:value-of select="cog:value[6]" />"},
          {"v": <xsl:value-of select="cog:value[7]" />},
          {"v": <xsl:value-of select="cog:value[8]" />},
          {"v": <xsl:value-of select="cog:value[9]" />},
          {"v": <xsl:value-of select="cog:value[10]" />},
          {"v": "<xsl:value-of select="cog:value[11]" />"}
        ]}<xsl:if test="position() != last()">,</xsl:if>
      </xsl:for-each>
      ]
    }
  </xsl:template>
</xsl:stylesheet>

以下是 JavaScript 执行转换的片段...

JavaScript

// create xsl processor
var xslProcessor = new XSLTProcessor();
xslProcessor.importStylesheet(sender.target.responseXML);  // responseXML = result from loading xsl file above

// perform transformation
var jsonData = xslProcessor.transformToFragment(sender.get_xml(), document).textContent;  // get_xml() = result from loading xml file above

// load google data table
dataTableSummary = new google.visualization.DataTable(jsonData);

使用这种方法,在 google chrome...

加载 3.1 MB 的 XML 数据平均需要 1.1 秒

加载 3.6 MB 的 XML 数据平均需要 1.4 秒

其中包括通过 XMLHttpRequest

加载 XML 和 XSL 文件的时间

单独执行转换所花费的时间,3.6 MB 大约需要 300 毫秒...

没有遇到过 运行 内存不足 的任何问题...