【问题标题】:Get XML tags from asXML()从 asXML() 获取 XML 标签
【发布时间】:2015-07-02 14:39:06
【问题描述】:

我正在解析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] 等中的标签?):

【问题讨论】:

  • 所以你本质上想要一个递归函数来遍历整个元素树(或者从任何元素开始,并不是说它真的有区别)并将每个标签名称及其内容作为原始文本获取?跨度>
  • @speibus 是的!这正是我想做的。我现在是否以错误的方式解决这个问题?如果是这样,我应该如何改变我正在做的事情?

标签: php xml simplexml


【解决方案1】:

我想将此数据移动到一个 MySQL 数据库中,其列与文件的标签匹配。

你的问题有两个方面。

问题的第一部分是对数据库结构进行自省。即获取所有表名,获取这些表的列名。大多数现代数据库都提供此功能,MySQL 也是如此。在 MySQL 中,这些是 INFORMATION_SCHEMA Tables。您可以像查询普通数据库表一样查询它们。我一般推荐 PDO 在 PHP 中,mysqli 自然也能完美地完成这项工作。

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

例如(如果我没看错的话)您将 Message-&gt;SettlementReport-&gt;SettlementData 标识为第一个 "table"。对于那个 特定 示例,这很简单,因为 &lt;SettlementData&gt; 只有可以表示列名称(元素名称)和值(文本内容)的子元素。这很容易:

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

如您所见,在 foreach 子句中指定 key 分配将为您提供带有 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 中提供的 Iterator 中受益,SimpleXMLElement 您通过 SimpleXMLElement 访问em>$xml-&gt;...-&gt;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)映射到二维结构(数据库表)现在可能总是那么简单。

如果您正在查看可能的结果(通常会出现数据丢失或数据重复),则在之前的问答中给出了一个更复杂的 PHP 示例:

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

我希望这会有所帮助,请在下面以 cmets 的形式提供任何反馈。您的问题可能会或可能不会减少问题,因此希望这有助于您决定如何/在哪里继续。

【讨论】:

  • 谢谢!这确实有助于解释解析 XMLl 的过程。我最终使用您的第三个示例来访问文件的树结构。
【解决方案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);
?>

【讨论】:

    猜你喜欢
    • 2018-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多