Parse through unknown XML(解析未知的XML)
本文介绍了解析未知的XML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我制作了一个简单的工具,允许您使用XML文件的URL填充输入字段。 它应该显示所有节点,以便用户可以将它们与数据库字段相匹配,我为一个具有两个"主要"节点的XML文件工作。 XML文件示例:
<foods>
<food>
<name>ravioli</name>
<recipe>food.com/ravioli</recipe>
<time>10 minutes</time>
</food>
<food>
<name>ravioli</name>
<recipe>food.com/ravioli</recipe>
<time>10 minutes</time>
</food>
</foods>
这将返回一个列表,该列表显示
name
recipe
time
问题是当某人想要使用没有两个"主要"节点的XML文件时。例如,它缺少<food>
节点。在这种情况下,它将无法显示结果,因为我的PHP代码预期为2,而不是1。
我的代码如下:
// Fetch the XML from the URL
if (!$xml = simplexml_load_file($_GET['url'])) {
// The XML file could not be reached
echo 'Error loading XML. Please check the URL.';
} else {
// Parse through the XML and fetch the nodes
$child = $xml->children();
foreach($child->children() as $key => $value) {
echo $key."<br>";
}
}
是否有方法可以从任何XML文件中获取我想要的节点,而不考虑父节点的数量?
推荐答案
您可以使用XPath从XMLDOM查询数据。在PHP中可以使用DOMXPath::EVALUATE()方法访问它。第二个参数是上下文,因此您的表达式可以相对于另一个节点。将其转换为记录列表(用于数据库、CSV等)。将需要几个步骤。从一些引导开始:
$xml = <<<'XML'
<foods>
<food>
<name>ravioli 1</name>
<recipe>food.com/ravioli-1</recipe>
<time unit="minutes">10</time>
</food>
<food>
<name>ravioli 2</name>
<recipe>food.com/ravioli-2</recipe>
<time unit="minutes">11</time>
</food>
</foods>
XML;
$dom = new DOMDocument();
$dom->loadXml($xml);
$xpath = new DOMXpath($dom);
首先,我们需要定义哪个XML元素定义记录,然后定义哪些元素定义字段。
所以让我们构建一个可能的记录路径和字段路径的列表:
$paths = [];
$leafs = [];
foreach ($xpath->evaluate('//*|//@*') as $node) {
$isPath = $xpath->evaluate('count(@*|*) > 0', $node);
$isLeaf = !($xpath->evaluate('count(*) > 0', $node));
$path = '';
foreach ($xpath->evaluate('ancestor::*', $node) as $parent) {
$path .= '/'.$parent->nodeName;
}
$path .= '/'.($node instanceOf DOMAttr ? '@' : '').$node->nodeName;
if ($isLeaf) {
$leafs[$path] = TRUE;
}
if ($isPath) {
$paths[$path] = TRUE;
}
}
$paths = array_keys($paths);
$leafs = array_keys($leafs);
var_dump($paths, $leafs);
输出:
array(3) {
[0] =>
string(6) "/foods"
[1] =>
string(11) "/foods/food"
[2] =>
string(16) "/foods/food/time"
}
array(4) {
[0] =>
string(16) "/foods/food/name"
[1] =>
string(18) "/foods/food/recipe"
[2] =>
string(16) "/foods/food/time"
[3] =>
string(22) "/foods/food/time/@unit"
}
接下来向用户显示可能的记录路径。用户需要选择一个。知道记录路径,从Leafs数组构建一个可能的字段路径列表:
$path = '/foods/food';
$fieldLeafs = [];
$pathLength = strlen($path) + 1;
foreach ($leafs as $leaf) {
if (0 === strpos($leaf, $path.'/')) {
$fieldLeafs[] = substr($leaf, $pathLength);
}
}
var_dump($fieldLeafs);
输出:
array(4) {
[0] =>
string(4) "name"
[1] =>
string(6) "recipe"
[2] =>
string(4) "time"
[3] =>
string(10) "time/@unit"
}
显示一些允许用户为每个字段选择路径的对话框。
$fieldDefinition = [
'title' => 'name',
'url' => 'recipe',
'needed_time' => 'time',
'time_unit' => 'time/@unit'
];
现在使用路径和映射来构建记录数组:
$result = [];
foreach ($xpath->evaluate($path) as $node) {
$record = [];
foreach ($fieldDefinition as $field => $expression) {
$record[$field] = $xpath->evaluate(
'string('.$expression.')',
$node
);
}
$result[] = $record;
}
var_dump($result);
输出:
array(2) {
[0] =>
array(4) {
'title' =>
string(9) "ravioli 1"
'url' =>
string(18) "food.com/ravioli-1"
'needed_time' =>
string(2) "10"
'time_unit' =>
string(7) "minutes"
}
[1] =>
array(4) {
'title' =>
string(9) "ravioli 2"
'url' =>
string(18) "food.com/ravioli-2"
'needed_time' =>
string(2) "11"
'time_unit' =>
string(7) "minutes"
}
}
完整示例位于:https://eval.in/118012
示例中的XML从未转换为泛型数组。这样做将意味着信息丢失和存储翻倍。所以不要。从XML中提取结构信息,让用户定义映射。使用XPath提取数据并直接以结果格式存储。
这篇关于解析未知的XML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
沃梦达教程
本文标题为:解析未知的XML
基础教程推荐
猜你喜欢
- 超薄框架REST服务两次获得输出 2022-01-01
- XAMPP 服务器不加载 CSS 文件 2022-01-01
- 在 PHP 中强制下载文件 - 在 Joomla 框架内 2022-01-01
- mysqli_insert_id 是否有可能在高流量应用程序中返回 2021-01-01
- 如何在 PHP 中的请求之间持久化对象 2022-01-01
- 在多维数组中查找最大值 2021-01-01
- Libpuzzle 索引数百万张图片? 2022-01-01
- 通过 PHP SoapClient 请求发送原始 XML 2021-01-01
- 在 Woocommerce 中根据运输方式和付款方式添加费用 2021-01-01
- WooCommerce 中选定产品类别的自定义产品价格后缀 2021-01-01