将大型XML文件转换为关系数据库

13

我正在试图找到最好的方法来完成以下任务:

  1. 每天从第三方网站下载一个大型XML文件(1GB)
  2. 将该XML文件转换为服务器上的关系型数据库
  3. 添加功能以搜索数据库

对于第一部分,这是需要手动完成的还是可以使用cron完成?

与XML和关系型数据库相关的大多数问题和答案都涉及Python或PHP。使用javascript/nodejs也能行吗?

如果这个问题更适合其他的StackExchange论坛,请告诉我,我会把它移动到那里。

下面是xml代码的示例:

<case-file>
  <serial-number>123456789</serial-number>
    <transaction-date>20150101</transaction-date>
      <case-file-header>
       <filing-date>20140101</filing-date>
      </case-file-header>
      <case-file-statements>
       <case-file-statement>
        <code>AQ123</code>
        <text>Case file statement text</text>
       </case-file-statement>
       <case-file-statement>
        <code>BC345</code>
        <text>Case file statement text</text>
       </case-file-statement>
     </case-file-statements>
   <classifications>
  <classification>
   <international-code-total-no>1</international-code-total-no>
   <primary-code>025</primary-code>
  </classification>
 </classifications>
</case-file>

以下是有关这些文件将如何使用的更多信息:

所有XML文件将采用相同格式。每个记录中可能有几十个元素。这些文件由第三方每天更新(并在第三方网站上以压缩文件的形式提供)。每天的文件都代表了新的案件文件和更新的案件文件。

目标是允许用户搜索信息并在页面上(或生成的pdf/excel文件中)组织这些搜索结果。例如,用户可能想查看包含特定单词在<text>元素内的所有案件文件。或者用户可能想要查看包括主代码025 (<primary-code>元素)且在特定日期(<filing-date>元素)之后被提交的所有案件文件。

数据库中输入的唯一数据将来自XML文件 - 用户不会向数据库添加任何自己的信息。


根据文件类型,我认为在Node或许多PHP设置中可能无法(轻松)完成;如果您真的需要解析XML,则需要大量RAM...如果您可以“逐块”抓取XML(如果它是平面+线性的,例如RSS文件),那么任何东西都可以工作。您可以分离一个块,解析小片段,然后使用新插入的行更新数据库。 - dandavis
@dandavis 谢谢您。您所说的“平面+线性”,是指不超过一级深度吗? - Ken
基本上,离散部分的开始和结束很重要。如果标签周围有空格和可预测性,则可以可靠地解析其中的片段。如果您需要从“顶部”获取属性,这些属性恰好位于“左侧”的120mb处,则需要努力连接这些部分。但是考虑到RSS,我可以从中间切割一块,查找第一个“<item>”和下一个“</item>”,并获得所需内容,前提是我提前缓存了频道信息... - dandavis
@dandavis,我添加了一个XML代码示例。有成千上万的块以<case-file>开头和结尾。这是可以逐个块解析的吗? - Ken
为什么一定要用PHP?是因为它将成为一个更大的使用PHP的系统/平台的一部分,还是其他原因? - Rcynic
@Rcynic,它绝对不需要是PHP。我更喜欢使用node.js。 - Ken
3个回答

8

所有步骤都可以使用node.js完成。有一些模块可用于帮助您完成每个任务:

    • node-cron:可让您轻松地在node程序中设置cron任务。另一个选择是在操作系统上设置cron任务(针对您喜欢的操作系统有很多资源可用)。
    • download:用于轻松从URL下载文件的模块。
  1. xml-stream:允许您流式传输文件并注册事件,当解析器遇到特定的XML元素时触发这些事件。我已成功使用此模块来解析KML文件(尽管它们比您的文件小得多)。

  2. node-postgres:PostgreSQL的node客户端(我相信还有其他常见RDBMS的客户端可用,但目前我只使用过PG)。

这些模块大多都有非常好的示例,可以帮助您入门。以下是您可能设置XML流部分的方式:

var XmlStream = require('xml-stream');
var xml = fs.createReadStream('path/to/file/on/disk'); // or stream directly from your online source
var xmlStream = new XmlStream(xml);
xmlStream.on('endElement case-file', function(element) {
    // create and execute SQL query/queries here for this element
});
xmlStream.on('end', function() {
    // done reading elements
    // do further processing / query database, etc.
});

由于您的数据似乎没有任何关系(扁平记录),因此您可以将每个记录保存在NoSQL数据库中(例如mongo db)。所有提到的查询都应该很容易从用户输入中编写/生成。数据以JSON格式存储和访问,使得在node.js中访问它非常容易。 - forrert

6

您确定需要将数据放入关系型数据库中,还是只想进行一般搜索?

数据中似乎没有实际的“关系”,因此将其放入文档搜索索引(如ElasticSearch)可能更简单。

任何自动XML到JSON转换器都可能会产生适当的输出。大文件大小是一个问题。这个库,尽管其摘要说“不是流式的”,但如果您检查源代码,它实际上是流式的,因此它适合您使用。


不,我不确定。那是我正在努力弄清楚的事情之一。我想允许用户通过代码、序列号、名称等搜索数据。上面的XML是实际XML文件中所有各种字段的非常简化版本。目标是允许快速搜索,并且在最终显示数据的方式上具有灵活性。 - Ken
他们想从数据库中检索哪种类型的数据?所有的XML文件格式都相同吗?是否存在其他关系或字段在当前示例XML文件上不明显?也许提供更多的数据示例和对数据使用计划的描述会有所帮助。 - Taraz
如果一个实体中没有包含指向另一个实体的字段(例如通过ID),那么您可能不需要关系型数据库。 - mwhite
@Taraz 我已经在问题中添加了更多信息。希望这有所帮助。如果您需要更多的澄清,请告诉我。 - Ken

3

我有一个与XML文件相关的任务,正如您所写的那样。这是我使用的原则:

  1. 将所有传入的文件按原样存储在DB中(XMLTYPE),因为我需要源文件信息;
  2. 对所有传入的文件进行XSL转换。例如,我看到这里有三个实体:fileInfo、fileCases、fileClassification。您可以编写XSL转换来编译3种实体类型的源文件信息(在标签FileInfo、FileCases、FileClassification中);
  3. 当您有输出转换后的XML时,可以创建3个过程,将数据插入DB中(每个实体在DB区域中)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接