php - 如何为某个字段具有某个值的所有产品提取 xml 数据?
问题描述
XML 文件包含 1000 个产品条目。其中一些为国家葡萄牙。我只想获取国家为葡萄牙的产品,并将该信息写入我的服务器上的新 XML 文件。我将如何在 PHP 中做到这一点?
XML 内容结构:
<products>
<product ID="38450">
<name>Aparthotel Alfagar</name>
<price currency="EUR">239.00</price>
<URL>https://website.com/</URL>
<images>
<image>https://website.com/1.jpg</image>
<image>https://website.com/2.jpg</image>
<image>https://website.com/3.jpg</image>
</images>
<description>
<![CDATA[<p>some text</p>]]>
</description>
<categories/>
<properties>
<property name="country">
<value>Portugal</value>
</property>
<property name="lowestPrice">
<value>239.00</value>
</property>
<property name="lowestPriceDate">
<value>13-01-2020</value>
</property>
</properties>
<variations/>
</product>
<!-- more product entries -->
我的方法是这样开始的:
<?php
// Define source
$source_url = 'https://website.net/?encoding=utf-8&type=xml&id=';
// Define target
$file_url = '/home/website/public_html/media/';
$file_ext = '.xml';
// Load data
$array = simplexml_load_file($source_url.'654321');
// Filter data
$results_portugal = '';
foreach($array->product->properties->property->value['Portugal'] as $results) {
}
// Create datafiles
copy ($results_portugal,$file_url.'portugal'.$file_ext);
显然我很快就被卡住了。谁能帮帮我?提前谢谢了!
解决方案
您可以使用 XPath 表达式在 SimpleXML 或 DOM 中获取 XML 的一部分:
$products = new SimpleXMLElement($xml);
var_dump(
count(
$products->xpath('//product[properties/property[@name = "country"]/value = "Portugal"]')
)
);
var_dump(
count(
$products->xpath('//product[properties/property[@name = "country"]/value = "Spain"]')
)
);
然而,这里不是在 SimpleXML 中复制节点的“好”方式。DOM 允许:
// create source document and load XML
$source = new DOMDocument();
$source->loadXML($xml);
$xpath = new DOMXpath($source);
// create target document and append root node
$target = new DOMDocument();
$target->appendChild($target->createElement('products'));
$expression = '//product[properties/property[@name = "country"]/value = "Portugal"]';
// iterate filtered nodes
foreach ($xpath->evaluate($expression) as $product) {
// import node into target document and append
$target->documentElement->appendChild(
$target->importNode($product, TRUE)
);
}
echo $target->saveXML();
对于非常大的 XML,您需要使用 XMLReader/XMLWriter。它们允许您仅将 XML 文件的一部分加载到内存中。最初这里不是复制节点的简单方法,但我将其添加到FluentDOM。
// Create the target writer and add the root element
$writer = new \FluentDOM\XMLWriter();
$writer->openUri('php://stdout');
$writer->setIndent(2);
$writer->startDocument();
$writer->startElement('products');
// load the source into a reader
$reader = new \FluentDOM\XMLReader();
$reader->open('data://text/plain;base64,'.base64_encode($xml));
// iterate the product elements - the iterator expands them into a DOM node
foreach (new FluentDOM\XMLReader\SiblingIterator($reader, 'product') as $product) {
/** @var \FluentDOM\DOM\Element $product */
// validate country property
if ($product('properties/property[@name = "country"]/value = "Portugal"')) {
// write expanded node to the output
$writer->collapse($product);
}
}
$writer->endElement();
$writer->endDocument();
推荐阅读
- javascript - jsPDF显示打印页面而不是下载文件
- python - 按百分比随机划分和存储 SQL 表
- ios - Swift 日期生成问题
- python - 我使用哪个小部件的 after 方法是否重要?
- r - 通过使用 group_split 和 group_map 对变量进行分组,使用 tabyl 制表
- ansible - 使用 pip 命令时出现 ansible 抛出错误
- python - ValueError:长度不正确的密文
- java - 在另一种方法中出现“字符串索引超出范围”的错误?
- regex - 适用于日志文件中多个匹配项的正则表达式 expr 以创建警报
- java - 无法反序列化所有对象的 ArrayList - 只有第一个对象被反序列化