【发布时间】:2019-01-14 17:39:02
【问题描述】:
我有多个 XML 示例文件,我想将它们转换为 CSV,但是对于不同的 XML 文件会有多个不同的属性/节点,因此我不想硬编码不同的属性。我希望输出将列标题显示为第一行,然后每个节点/记录都像传统的列和行电子表格一样垂直显示。 这是一个示例 XML:
<?xml version="1.0" encoding="UTF-8"?>
<sd:root xmlns:wd="urn:com.sample/bsvc" sd:version="v31.0">
<sd:Put_Job_Profile_Request sd:Add_Only="0">
<sd:Job_Profile_Data>
<sd:Job_Code>30000</sd:Job_Code>
<sd:Effective_Date>1900-01-01</sd:Effective_Date>
<sd:Job_Profile_Basic_Data>
<sd:Job_Title>Chief Executive Officer</sd:Job_Title>
</sd:Job_Profile_Basic_Data>
</sd:Job_Profile_Data>
</sd:Put_Job_Profile_Request>
<sd:Put_Job_Profile_Request sd:Add_Only="0">
<sd:Job_Profile_Data>
<sd:Job_Code>30100</sd:Job_Code>
<sd:Effective_Date>1900-01-01</sd:Effective_Date>
<sd:Job_Profile_Basic_Data>
<sd:Job_Title>Administrator Job Profile</sd:Job_Title>
</sd:Job_Profile_Basic_Data>
</sd:Job_Profile_Data>
</sd:Put_Job_Profile_Request>
<sd:Put_Job_Profile_Request sd:Add_Only="0">
<sd:Job_Profile_Data>
<sd:Job_Code>30200</sd:Job_Code>
<sd:Effective_Date>1900-01-01</sd:Effective_Date>
<sd:Job_Profile_Basic_Data>
<sd:Inactive>0</sd:Inactive>
<sd:Job_Title>Facilities & Grounds Maintenance Attendant</sd:Job_Title>
<sd:Include_Job_Code_in_Name>0</sd:Include_Job_Code_in_Name>
<sd:Job_Profile_Private_Title>Maintenance Job Title</sd:Job_Profile_Private_Title>
<sd:Job_Profile_Summary>Maintain cleanliness of the campus building throughout the day and fulfill special requests as needed.</sd:Job_Profile_Summary>
<sd:Job_Description><p>Job Description<b> rich text!</b></p></sd:Job_Description>
<sd:Additional_Job_Description><p><b><i><span class="emphasis-2"><u>Additional</u></span></i></b> Job Description<b> rich text!</b></p></sd:Additional_Job_Description>
<sd:Work_Shift_Required>0</sd:Work_Shift_Required>
<sd:Public_Job>1</sd:Public_Job>
</sd:Job_Profile_Basic_Data>
</sd:Job_Profile_Data>
</sd:Put_Job_Profile_Request>
<sd:Put_Job_Profile_Request sd:Add_Only="0">
<sd:Job_Profile_Data>
<sd:Job_Code>30300</sd:Job_Code>
<sd:Effective_Date>1900-01-01</sd:Effective_Date>
<sd:Job_Profile_Basic_Data>
<sd:Inactive>0</sd:Inactive>
<sd:Job_Title>Sample_Job_Title</sd:Job_Title>
<sd:Include_Job_Code_in_Name>0</sd:Include_Job_Code_in_Name>
<sd:Job_Profile_Summary>Sample Job Profile Summary</sd:Job_Profile_Summary>
<sd:Job_Description>Sample Job Description</sd:Job_Description>
<sd:Additional_Job_Description>Sample Additional Job Description</sd:Additional_Job_Description>
<sd:Work_Shift_Required>1</sd:Work_Shift_Required>
</sd:Job_Profile_Basic_Data>
</sd:Job_Profile_Data>
</sd:Put_Job_Profile_Request>
</sd:root>
我使用但输出错误的代码:
require 'csv'
require 'nokogiri'
file = File.read('jobProfile.xml')
doc = Nokogiri::XML(file)
a = []
CSV.open('xmloutput.csv', 'wb') do |csv|
csv << doc.at('.').search('*').map(&:name)
doc.search('.').each do |x|
csv << x.search('*').map(&:text)
end
end
每组记录的列标题和数据水平设置。但我想迭代数据并保留一行列标题。如果不对每个属性进行硬编码,我不确定如何做到这一点:/ 请帮忙,因为我还是编程新手,我已经尝试了一周找到解决方案:(
【问题讨论】:
-
不清楚这里的问题是什么。与往常一样,尝试将这个大问题分解为更小的问题,以便解决方案更简单。
-
我正在尝试将列标题解析到第一行,并像传统的 Excel 电子表格一样向下迭代每个节点/记录的数据。正如您从屏幕截图中看到的那样,每个记录:列和数据都是从代码中水平提取的,这不是我想要的。请指教。
-
CSV 以
csv << row形式工作,因此您可能需要在将其填充到csv之前逐步创建一行。您应该在添加之前完成该行,而不是随手添加。 -
如果您澄清预期的输出会有所帮助 - 例如,您希望此 XML 示例使用什么 CSV?我猜你希望每个“Put_Job_Profile_Request”都是一行。但是,我不太确定预期的列标题是什么 - 特别是“Job_Profile_Basic_Data”中的那些
标签: ruby xml csv nokogiri export-to-csv