我的完整XML在下面命名为user.xml:
<?xml version="1.0" encoding="utf-8"?>
<users>
<user id='1'>
<user_name>John</user_name>
<user_lastname>Doe</user_lastname>
<previous_requisitions>
<requisition_code>X321</requisition_code>
<requisition_code>Y321</requisition_code>
<requisition_code>Z321</requisition_code>
</previous_requisitions>
<user_requisition>
<requisition_code>X123</requisition_code>
<requisition_title>Ssr Dev 1</requisition_title>
<requisition_relocation>10~20%</requisition_relocation>
</user_requisition>
</user>
<user id='2'>
<user_name>James</user_name>
<user_lastname>Smith</user_lastname>
<previous_requisitions>
<requisition_code>X222</requisition_code>
<requisition_code>Y222</requisition_code>
<requisition_code>Z222</requisition_code>
</previous_requisitions>
<user_requisition>
<requisition_code>Y123</requisition_code>
<requisition_title>Sr Dev 1</requisition_title>
<requisition_relocation>20~30%</requisition_relocation>
</user_requisition>
</user>
<user id='3'>
<user_name>Jess</user_name>
<user_lastname>Ssej</user_lastname>
<previous_requisitions>
<requisition_code>X111</requisition_code>
<requisition_code>Y111</requisition_code>
<requisition_code>Z111</requisition_code>
</previous_requisitions>
<user_requisition>
<requisition_code>Z123</requisition_code>
<requisition_title>Jr Dev 2</requisition_title>
<requisition_relocation>0~10%</requisition_relocation>
</user_requisition>
</user>
</users>
因为在XML和借助在线资源和stackoverflow的帮助下不是很好;能够创建这个PHP脚本:
<?php
$file='user.xml';
if (file_exists($file)) {
$xml = simplexml_load_file($file);
$f = fopen('user.csv', 'w');
// array to hold the field names
$headers = array();
// loop through the first set of fields to get names
foreach ($xml->user->children() as $field) {
// put the field name into array
$headers[] = $field->getName();
}
// print headers to CSV
fputcsv($f, $headers, ',', '"');
foreach ($xml->user as $users) {
fputcsv($f, get_object_vars($users), ',', '"');
}
fclose($f);
}
?>
当我运行PHP脚本时,文件被写入但有一些问题:
请参阅下面的结果屏幕截图(在excel中打开):
问题:
因为看起来$ headers = array();没有正确循环。 PHP脚本上的任何修复都能正确显示XML中的所有标题和数据吗?
我只需要将以下子节点导出为CSV,因此这6个也将是标题:
USER_ID,
USER_NAME,
user_lastname,
user_requisition_code,
user_requisition_title,
user_requisition_relocation,
请指导我如何制作剧本&#34; selective&#34;省略或不包括XML中的其他子节点,如:
previous_requisitions
requisition_code
非常感谢帮助和新年快乐!
旁注:将坚持使用开源脚本,希望没有人会回答建议使用专有软件。答案 0 :(得分:0)
对于1.)你可能觉得$ headers = array();没有正确循环,但我没有看到循环有任何问题。它完全没问题,完全遵循SimpleXML记录的内容:http://php.net/book.simplexml。
对于2.)我想说你想跳过分组元素中的所有同名元素(如果有的话)。这有点让我想起了这个question和answer但是在这个例子中,具有相同名称和相同父级的兄弟姐妹被插入到其他行中。在您的情况下,您只想跳过它们。 对于您来说,通过xpath查询您正在寻找的值可能更容易。由于您查询的元素也有一个甚至是列名的名称,因此它也应该可以正常工作。 (我将在下面的示例代码中显示两种变体)
对于3.)这应该是完全可能的。你给出的错误信息让我看起来你混淆了一些其他参数。它与将管道设置为分隔符无关(代码示例将使用管道符号“|
”作为CSV分隔符,它完全有效。)
话虽这么说,一个接近您在视觉中概述的问题(但缺少用户ID)的解决方案可能是:
$csv = new SplFileObject('php://output', 'w');
$csv->setCsvControl("|");
$users = iterator_to_array($xml->user, false);
foreach ($users as $index => $user) {
$fields = [];
foreach ($user->xpath('(*[not(./*)]|user_requisition/*)') as $field) {
$fields[$field->getName()] = trim($field);
}
// first iteration output headers
$index || $csv->fputcsv(array_keys($fields));
$csv->fputcsv($fields);
}
示例XML的示例输出是:
user_name|user_lastname|requisition_code|requisition_title|requisition_relocation
John|Doe|X123|"Ssr Dev 1"|10~20%
James|Smith|Y123|"Sr Dev 1"|20~30%
Jess|Ssej|Z123|"Jr Dev 2"|0~10%
映射的用例是一个稍微不同的代码:
$csv = new SplFileObject('php://output', 'w');
$csv->setCsvControl("|");
$fieldDefs = [
'user_id' => '@id',
'user_name' => 'user_name',
'user_lastname' => 'user_lastname',
'requisition_code' => 'user_requisition/requisition_code',
'requisition_title' => 'user_requisition/requisition_title',
'requisition_relocation' => 'user_requisition/requisition_relocation',
];
// output CSV headers
$csv->fputcsv(array_keys($fieldDefs));
$users = $xml->user;
foreach ($users as $user) {
$fields = [];
foreach ($fieldDefs as $fieldDef) {
$fields[] = $user->xpath($fieldDef)[0];
}
$csv->fputcsv($fields);
}
输出略有不同:
user_id|user_name|user_lastname|requisition_code|requisition_title|requisition_relocation
1|John|Doe|X123|"Ssr Dev 1"|10~20%
2|James|Smith|Y123|"Sr Dev 1"|20~30%
3|Jess|Ssej|Z123|"Jr Dev 2"|0~10%
第二个示例显示了如何将更具体的映射组合到标头。这有点明确,允许以与元素名称不同的方式命名标题。
我希望这些例子是不言自明的,但你可能偶然发现我做的事情与你可能做的不同。例如。我使用 SplFileObject 来执行CSV操作,它基本上与您使用的方法相同,但是以对象的形式保持代码更干净(因为不需要重复一些)参数)。
第二个例子中的XPath表达式对你来说可能是新的,但我希望它们只是通过查看数组和你给出的XML来实现自我解释。
这些示例应该向后兼容到PHP 5.4。