将大量CSV转换为特定的XML格式

时间:2015-08-15 21:09:05

标签: php xml csv

我有一个非常庞大的重量表,我需要转换为XML格式的CSV格式。我遇到的问题是我需要进入的XML格式与CSV的布局方式不完全吻合。

以下是CSV布局的一个小例子:

WEIGHT BREAK (LBS),WEIGHT BREAK (OZ),CA,AD,AE,AF,AG    
0.06,1,4.14,3.48,3.51,3.62,3.55    
0.13,2,4.59,3.97,4.04,4.24,4.1    
0.19,3,5.04,4.44,4.54,4.86,4.66

我需要将其转换为每个国家的以下内容:

<Module code='wtbship' feature='shipping'>
    <Method_Add>  
        <Method>CA</Method>
        <Handling>0.00</Handling>
        <Range>
            <Ceiling>0.06</Ceiling>
            <Rate>4.14</Rate>
        </Range>
        <Range>
            <Ceiling>0.13</Ceiling>
            <Rate>4.59</Rate>
        </Range>
        <Range>
            <Ceiling>0.19</Ceiling>
            <Rate>5.04</Rate>
        </Range>
    </Method_Add>
</Module>

每行中的第一个元素是我需要抓取的权重上限,然后每个国家/地区在每行中都有自己的元素,其中包含该权重上限的价格。

我正在使用CSV中的227个国家/地区。我知道如果每个国家都有一个阵列,我可以做到这一点,当我循环使用CSV时,我可以将重量和价格推到每个国家的阵列,但这似乎很多工作,我正在尝试找到一种更简单的方法。

我最初尝试使用perl但是切换到PHP,因为我对它更熟悉一点。这几乎就像我需要循环遍历列结构而不是行,但似乎不可能这样做。

任何人都可以提供任何可行的建议,或指出我正确的方向吗?

1 个答案:

答案 0 :(得分:1)

我认为你的概念已经相当不错了。您只是有点受限制,因为您认为可能存在更容易的方式(tm),您肯定希望拥有它。

甚至可能有,但首先我认为你已经解决了这个问题。这很重要,因为您可以尝试按照您的想法尽可能高效地完成解决方案。它从来没有反过来:嘿,我需要简单的解决方案。 1.)简单2.)解决方案。不,首先你需要一个解决方案,然后你可以考虑让它变得简单。而且当你发现你所拥有的解决方案不够容易时,你只需要考虑让它变得简单。

所以 easyiness 纯粹是相对到你的解决方案。

所以让我们一起看看你到目前为止所做的事情:

  

我正在使用CSV中的227个国家/地区。我知道如果每个国家都有一个阵列,我可以做到这一点,当我循环使用CSV时,我可以将重量和价格推到每个国家的阵列,但这似乎很多工作,我正在尝试找到一种更简单的方法。

首先考虑限制,以确定您的解决方案是否已经是解决方案或仅在理论上。你写的有227个国家。问题是,您的CSV文件中有多少行(记录)?你在问题中给出的例子只有三个(我猜不是)或者更多。还有多少? 1 000? 10 000? 10万? ...?

在您概述的时候,您在这里有一个产品:countries * records。所以,如果你让我们说250 countries并且你有100 000 records,这将是数组中的25 000 000个条目。根据一个数组条目将占用多少内存,您将达到内存限制。所以这可能甚至可能是最简单的解决方案你已经得到它不会起作用所以根本就不是解决方案。

这意味着,尽管您要求提供更简单的解决方案,但实际上甚至可能需要更多复杂的解决方案,因为到目前为止您的解决方案是容易,甚至根本不起作用。

哪一种以及如何以简单的方式完成,很大程度上取决于您的问题尚未明确的要求:

  • 是否需要根据原始CSV文件中的国家/地区数据或记录顺序采取某些元素顺序?
  • 输入文件是否会在事务进行时发生变化,或者保存为假设CSV文件根本不会发生变化?

根据这些细节,解决方案的算法可能会有很大差异。特别是如果有命令要保留/实现。

例如,以下XML是否也被视为有效?它在技术上对相同的信息进行编码,但可能不合适:

<Module code='wtbship' feature='shipping'>
    <Method_Add>
        <Method>CA</Method>
        <Handling>0.00</Handling>
        <Range>
            <Ceiling>0.06</Ceiling>
            <Rate>4.14</Rate>
        </Range>
    </Method_Add>
    <Method_Add>
        <Method>CA</Method>
        <Handling>0.00</Handling>
        <Range>
            <Ceiling>0.13</Ceiling>
            <Rate>4.59</Rate>
        </Range>
    </Method_Add>
    <Method_Add>
        <Method>CA</Method>
        <Handling>0.00</Handling>
        <Range>
            <Ceiling>0.19</Ceiling>
            <Rate>5.04</Rate>
        </Range>
    </Method_Add>
</Module>

但是如果合适,它可能允许在另一个之后处理CSV文件的一个记录(行)。这可以大大简化代码。

这将允许您对迭代进行编码,该迭代返回值中的所有值集,然后是国家顺序:

iteration #0: Array
(
    [country] => CA
    [handling] => 0.00
    [ceiling] => 0.06
    [rate] => 4.14
)
iteration #1: Array
(
    [country] => AD
    [handling] => 0.00
    [ceiling] => 0.06
    [rate] => 3.48
)
iteration #2: Array
(
    [country] => AE
    [handling] => 0.00
    [ceiling] => 0.06
    [rate] => 3.51
)

这可以像将 CsvParser 一样简单地用作Generator,这种用法非常简单:

$parser = new CsvParser('/path/to/file.csv');

foreach($parser as $record) {
    print_r($record);
}

(输出类似于迭代#0到上面的迭代#1示例)

如前所述,这取决于数据的顺序是否足够。所以只有一个例子,这可以产生影响 - 积极而消极。

此示例不包括创建XML。在这种情况下,可以使用 XmlEncoder

轻松添加
$parser = new CsvParser('/path/to/file.csv');
$encoder = new XmlEncoder('/path/to/file.xml', $parser);
$encoder->encode();

正如这个小例子所示,它可能已经是一个非常普遍的解决方案,因为它将工作分为两部分:

首先是解析CSV,第二是编码XML。有两个对象可以解决这个问题。接口与文件系统有关。

解析器和编码器之间的契约是a) Traversable 接口和b)每个记录的格式(这里是一个带有四个键的数组)。

然后输出可能是这样的:

<?xml version="1.0"?>
<Module>
 <Method_Add>
  <Method>CA</Method>
  <Handling>0.00</Handling>
  <Range>
   <Ceiling>0.06</Ceiling>
   <Rate>4.14</Rate>
  </Range>
 </Method_Add>
 <Method_Add>
  <Method>AD</Method>
  <Handling>0.00</Handling>
  <Range>
   <Ceiling>0.06</Ceiling>
   <Rate>3.48</Rate>
  </Range>
 </Method_Add>
 <Method_Add>
  <Method>AE</Method>
  <Handling>0.00</Handling>
  <Range>
   <Ceiling>0.06</Ceiling>
   <Rate>3.51</Rate>
  </Range>
 </Method_Add>
...

接下来,这个可能是错误的元素顺序,这个例子肯定也缺少一些细节(比如 Module 文档元素的属性)但它有希望表明,回答一个问题更简单的方式(tm)并不是那么容易,因为它不容易被问到它。

更重要的是,您确认您的解决方案确实符合您的需求,并且在您进行测试后明确表示您需要获得一个更难以找到的解决方案它的解决方案;)。

您可以在此处找到异地的工作示例:online demo