php - 当 xml 文件有多个匹配字段时,XML 到 MySQL

标签 php mysql xml

我一直在使用加载 XML 对 XML 到 Mysql 进行一些工作。我过去用它很成功。与最新成果的不同之处在于,我们在 MySQL 中多次出现了一个字段名。示例如下:

<row>
<pictures>
        <picture name="Photo 1">
          <filename>image1.jpg</filename>
        </picture>
        <picture name="Photo 2">
          <filename>image2.jpg</filename>
        </picture>
        <picture name="Photo 4">
          <filename>image3.jpg</filename>
        </picture>
        <picture name="Photo 3">
          <filename>image4.jpg</filename>
        </picture>
        <picture name="Photo 7">
          <filename>image5.jpg</filename>
        </picture>
        <picture name="Photo 6">
          <filename>image6.jpg</filename>
        </picture>
        <picture name="Photo 5">
          <filename>image7.jpg</filename>
        </picture>
        <picture name="Photo 8">
          <filename>image8.jpg</filename>
        </picture>
        <picture name="Photo 9">
          <filename>image9.jpg</filename>
        </picture>
      </pictures>
</row>

我需要将其导入到包含以下字段的 MySQL 表中:

  • 图片1
  • 图2
  • 图3
  • 图4
  • 图5
  • 图6
  • 图7
  • 图8
  • 图9

如您所见,“名称”属性不一定以正确的顺序出现,因此我需要按顺序简单地插入它们。所以第一个<filename>转到图 1,第二个 <filename>到图片2等等。

目前正在实现的是我总是以最后一个<picture>结束列表中的条目在表中。这是我的假设,因为该文件每次都被覆盖。

有什么想法可以实现吗?我发现了与此类似的问题,但目前还没有答案,并且一直在寻找一段时间。文件的其余部分加载正常,因为它们具有唯一的字段名称并且可以轻松映射到 MySQL 列,但我正在努力解决这个问题。

最佳答案

由于 XML 与您的目标格式不匹配,您需要先对其进行转换。传统上这是使用 XSLT 完成的,但您也可以使用 PHP 中的 XMLReaderXMLWriter 来完成,其优点是不需要保留整个 XML 文档在内存中。

XMLReaderIterator package支持此类操作,an example is already given with the library .

通过采用您的特定案例和名为 pictures.xml 的示例性输入文件创建该示例代码的修改并将输出保留为标准输出以用于演示目的允许我引用以下摘录:

[... starts like examples/read-write.php] 

/** @var $iterator XMLWritingIteration|XMLReaderNode[] */
$iterator = new XMLWritingIteration($writer, $reader);
$writer->startDocument();

$rename = ['row' => 'resultset', 'pictures' => 'row'];

$trimLevel    = null;
$pictureCount = null;

foreach ($iterator as $node) {
    $name         = $node->name;
    $isElement    = $node->nodeType === XMLReader::ELEMENT;
    $isEndElement = $node->nodeType === XMLReader::END_ELEMENT;
    $isWhitespace = $node->nodeType === XMLReader::SIGNIFICANT_WHITESPACE;

    if (($isElement || $isEndElement) && $name === 'filename') {
        // drop <filename> opening and closing tags
    } elseif ($isElement && $name === 'picture') {
        $writer->startElement('field');
        $writer->writeAttribute('name', sprintf('picture%d', ++$pictureCount));
        $trimLevel = $node->depth;
    } elseif ($trimLevel && $isWhitespace && $node->depth > $trimLevel) {
        // drop (trim) SIGNIFICANT_WHITESPACE
    } elseif ($isElement && isset($rename[$name])) {
        $writer->startElement($rename[$name]);
        if ($rename[$name] === 'row') {
            $pictureCount = 0;
        }
    } else {
        $iterator->write();
    }
}

这是一个由 XMLReaderXMLWriter 对象组成的 XMLWritingIteration。该迭代允许您接管输入文档中的所有内容(通过 $iterator->write() )并仅在某些情况下进行所需的更改:

  • 放下<filename></filename>标签
  • 创建<field>具有正确名称属性的元素使图片按文档顺序排列(Mysql XML 命名法)
  • 删除重要的空格作为<filename>标签也被删除
  • 重命名 <row> 中的文档元素至 <resultset> (Mysql XML 命名法)
  • 重命名 <pictures>元素到 <row> (同样是 Mysql XML 命名法)
  • 每个(输出)行重置图片字段的计数器
  • 其他一切保持原样

这样的转换会产生以下示例输出,其中包含您问题中提供的 XML:

<?xml version="1.0"?>
<resultset>
    <row>
        <field name="picture1">image1.jpg</field>
        <field name="picture2">image2.jpg</field>
        <field name="picture3">image3.jpg</field>
        <field name="picture4">image4.jpg</field>
        <field name="picture5">image5.jpg</field>
        <field name="picture6">image6.jpg</field>
        <field name="picture7">image7.jpg</field>
        <field name="picture8">image8.jpg</field>
        <field name="picture9">image9.jpg</field>
    </row>
</resultset>

关于Mysql使用的XML格式的更多信息,请看the Mysql documentation for the --xml commandline switch它描述了标准的 XML 输出格式,可以在 by LOAD XML 中阅读。 .

对于这个小例子,您也可以使用 XSLT,因为在内存中完成整个转换没有问题。但是,如果您需要查找内存(如果您处理 XML 数据库转储,则可能会发生这种情况),XMLWritingIteration 允许使用 XML Pull 解析器 (XMLReader) 进行基于迭代的 XML 转换和通过 XMLWriter 的仅转发 XML 输出。

关于php - 当 xml 文件有多个匹配字段时,XML 到 MySQL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31830556/

相关文章:

php - PHP Whoops错误处理程序电子邮件

mysql - 如何使用 perl 在 Windows V10 上访问 mysql V8?

javascript - 在 PHP 中,我从 mySQL 编码了一个 JSON 数组。我想在不同的 php 文件中解码它

android - 如何制作内联文本编辑器和 ImageView

php - "Notice: Undefined variable"、 "Notice: Undefined index"、 "Warning: Undefined array key"和 "Notice: Undefined offset"使用 PHP

php - 如何像在 Twitter 上一样在后台显示存储在数据库中的重复图像?

SQL返回在MySQL中删除非数字字符的字段

c# - XNA:加载和读取 XML 文件的最佳方式?

.net - 将类的所有属性序列化为 XML

javascript - 我的标题(位置)有问题