从asXML()获取XML标记

时间:2015-07-02 14:39:07

标签: php xml simplexml

我正在解析XML文档并使用asXML()获取嵌套代码的值。这工作正常,但我想将此数据移动到MySQL数据库,其列与文件的标记匹配。因此,我如何获得asXML()从中提取文本的标记?

这样我最终可以执行以下操作:INSERT INTO db.table (TheXMLTag) VALUES ('XMLTagText');

这是我现在的代码:

$xml = simplexml_load_file($target_file) or die ("Error: Cannot create object");

foreach ($xml->Message->SettlementReport->SettlementData as $main ){
    $value = $main->asXML();
    echo '<pre>'; echo $value; echo '</pre>';
}

foreach ($xml->Message->SettlementReport->Order as $main ){
    $value = $main->asXML();
    echo '<pre>'; echo $value; echo '</pre>';
}

这就是我的文件想要给你一个想法(基本上我如何获得[SettlementData],[0],[Fulfillment],[Item]等中的标签?): enter image description here

2 个答案:

答案 0 :(得分:2)

我尝试使用SimpleXML,但它会跳过文本数据。但是,使用Document Object Model扩展名可以使用。

这将返回一个数组,其中每个元素都是一个包含2个键的数组:tagtext,按照树的行进顺序返回。

<?php
// recursive, pass by reference (spare memory ? meh...)
// can skip non tag elements (removes lots of empty elements)
function tagData(&$node, $skipNonTag=false) {

   // get function name, allows to rename function without too much work
   $self = __FUNCTION__;

   // init
   $out      = array();
   $innerXML = '';

   // get document
   $doc = $node->nodeName == '#document'
      ? $node
      : $node->ownerDocument;

   // current tag
   // we use a reference to innerXML to fill it later to keep the tree order
   // without ref, this would go after the loop, children would appear first
   // not really important but we never know
   if(!(mb_substr($node->nodeName,0,1) == '#' && $skipNonTag)) {
      $out[] = array(
         'tag'  => $node->nodeName,
         'text' => &$innerXML,
      );
   }

   // build current innerXML and process children
   // check for children
   if($node->hasChildNodes()) {

      // process children
      foreach($node->childNodes as $child) {

         // build current innerXML
         $innerXML .= $doc->saveXML($child);

         // repeat process with children
         $out = array_merge($out, $self($child, $skipNonTag));
      }
   }

   // return current + children
   return $out;
}

$xml = new DOMDocument();
$xml->load($target_file) or die ("Error: Cannot load xml");
$tags = tagData($xml, true);
//print_r($tags);
?>

答案 1 :(得分:2)

  

我想将这些数据移动到一个MySQL数据库中,该数据库的列与文件的标记相匹配。

你的问题是两个折叠。

问题的第一部分是对数据库结构执行 introspection 。也就是说,获取所有表名并获取这些名称的列名。大多数现代数据库都提供此功能,MySQL也是如此。在MySQL中,那些是 INFORMATION_SCHEMA Tables 。您可以将它们作为普通数据库表进行查询。我通常建议在PHP中使用 PDO mysqli 自然也可以完美地完成工作。

第二部分是解析XML数据并将其数据映射到数据库表(您在问题中使用 SimpleXMLElement ,因此我与特别相关)。为此,您首先需要了解如何将XML中的数据映射到数据库。 XML文件没有像关系数据库表那样的2D结构,但它具有树结构。

例如(如果我正确阅读了您的问题),您将 Message->SettlementReport->SettlementData 标识为第一个“表格”。对于那个特定的示例,它很容易,因为<SettlementData>只有可以表示列名(元素名称)和值(文本内容)的子元素。为此它很容易:

header('Content-Type: text/plain; charset=utf-8');
$table = $xml->Message->SettlementReport->SettlementData;
foreach ($table as $name => $value ) {
    echo $name, ': ', $value, "\n";
}

如您所见,在 foreach 子句中指定分配将为您提供 SimpleXMLElement 的元素名称。或者,SimpleXMLElement::getName()方法也是这样做的(只是一个例子,只是代码略有不同):

header('Content-Type: text/plain; charset=utf-8');
$table = $xml->Message->SettlementReport->SettlementData;
foreach ($table as $value) {
    $name = $value->getName();
    echo $name, ': ', $value, "\n";
}

在这种情况下,您可以从 foreach SimpleXMLElement 中提供的 Iterator 这一事实中受益您通过 $xml->...->SettlementData 访问遍历所有子元素。

更通用的概念是Xpath。所以请耐心地向我介绍第三个例子 - 再次 - 做类似的输出:

header('Content-Type: text/plain; charset=utf-8');
$rows = $xml->xpath('/*/Message/SettlementReport/SettlementData');
foreach ($rows as $row) {
    foreach ($row as $column) {
        $name  = $column->getName();
        $value = (string) $column;
        echo $name, ': ', $value, "\n";
    }
}

然而,如前所述,将树结构(N-Depth)映射到2D结构(数据库表)现在可能总是那么直接。

如果你正在寻找可能的结果(通常会有数据丢失或数据重复),那么之前的Q&amp; A中会给出一个更复杂的PHP示例:

请注意:事实上,这种映射本身就很复杂,问题和答案都是从这种复杂性中继承而来的。这首先意味着那些可能不容易阅读但也许 - 更突出 - 可能不适用于你的问题。这些仅仅是为了拓宽您的观点并为某些场景提供一些示例。

我希望这有帮助,请以下面的评论形式提供任何反馈。你的问题可能会或可能没有问题,所以这有助于你决定如何/在哪里继续。