简体   繁体   中英

CSV to Specific XML with Powershell

I am trying to use powershell to convert a csv to an xml table. Is there a way that you can specify exactly what the xml will output.

Example CSV input: 
TIME,TEMP,HUMID,DEWPT
"03/07/2012 12:04:59",72.1,73.2,62.5
"03/07/2012 11:34:53",71.9,73.8,62.5
"03/07/2012 11:04:46",71.8,74.6,62.7
"03/07/2012 10:34:39",72.3,72.6,62.4
"03/07/2012 10:04:33",71.9,72.1,61.9

Example XML output:
<?xml version="1.0" encoding="UTF-8" ?> 
- <chart>
- <series>
  <value xid="0">03/07/2012 00:02:06</value> 
  <value xid="1">03/07/2012 00:32:17</value> 
  <value xid="2">03/07/2012 01:02:26</value> 
  <value xid="3">03/07/2012 01:32:35</value> 
  <value xid="4">03/07/2012 02:02:42</value>
  </series>
- <graphs>
- <graph gid="0" color="#32CD32" axis="right" title="Temperature">
  <value xid="0">43.1</value> 
  <value xid="1">44.0</value> 
  <value xid="2">43.6</value> 
  <value xid="3">43.1</value> 
  <value xid="4">42.7</value> 
  </graph>
- <graph gid="1" color="#FFD700" axis="left" title="Humidity">
  <value xid="0">64.6</value> 
  <value xid="1">100.0</value> 
  <value xid="2">57.7</value> 
  <value xid="3">71.6</value> 
  <value xid="4">44.3</value> 
  </graph>
  <graph gid="2" color="#8B008B" axis="left" title="Dewpoint">
  <value xid="0">30.4</value>
  <value xid="1">44</value>
  <value xid="2">28.4</value>
  <value xid="3">32.9</value>
  <value xid="4">22.6</value>
  </graph>
  </graphs>
  </chart>

The data may not line up 100%, I did not grab each sample piece from the same place, but you should get the drift. Is something like this possible?

Also... I maintain a large master-csv. Every hour two records are added to it. Is it possible to make the csv-to-xml increment smartly like that, or will I have to run the script against the master-csv each time. I know it will work running against the master-csv, but I am worried over time that it will take longer and longer as the list continues to grow. If I am able to add just the new entries, that would make it go much faster.

Does this work?

 $head = @'
 <?xml version="1.0" encoding="UTF-8" ?> 
 <chart>
 <series>
 '@

 $series = @'
 '@

 $temp_graph = @'
 </series>
 <graphs>
 <graph gid="0" color="#32CD32" axis="right" title="Temperature">

 '@

 $humid_graph = @'
 <graph gid="1" color="#FFD700" axis="left" title="Humidity">

 '@

 $dewpt_graph = @'
 <graph gid="2" color="#8B008B" axis="left" title="Dewpoint">

 '@

 $end = @'
 </graphs>
 </chart>
 '@

 $i = 0

 import-csv file.csv |
 foreach-object {

 $series += @"
 <value xid="$i">$($_.TIME)</value>

 "@

 $temp_graph += @"
 <value xid="$i">$($_.TEMP)</value>

 "@

 $humid_graph += @"
 <value xid="$i">$($_.HUMID)</value>

 "@

 $dewpt_graph += @"
 <value xid="$i">$($_.DEWPT)</value>

 "@

 $i++
 }
 $temp_graph,$humid_graph,$dewpt_graph | foreach {$_ += '<\graph>'
 $head + $series + $temp_graph + $humid_graph + $dewpt_graph + $end

This following script incrementally adds data to the xml (using regex and replace functionality). The csv file input.csv should contain only the new entries.

# filename: test.ps1

function Get-ScriptDirectory
{

$Invocation = (Get-Variable MyInvocation -Scope 1).Value
Split-Path $Invocation.MyCommand.Path
}
$csvpath = join-path (get-scriptdirectory) input.csv
$xmlpath = join-path (get-scriptdirectory) output.xml

if (!(test-path $xmlpath)) {
  @"
  <?xml version="1.0" encoding="UTF-8" ?> 
  <chart>
  <series>
  </series>
  <graphs>
  <graph gid="0" color="#32CD32" axis="right" title="Temperature">
  </graph>
  <graph gid="1" color="#FFD700" axis="left" title="Humidity">
  </graph>
  <graph gid="2" color="#8B008B" axis="left" title="Dewpoint">
  </graph>
  </graphs>
  </chart>
"@ | out-file -encoding "UTF8" $xmlpath
}

$xml = [System.IO.File]::ReadAllText($xmlpath)



$data = import-csv $csvpath

$counter = [int](([regex]‘xid="(\d*)"’).matches($xml) | foreach {$_.Groups[1].Value} | %{[int] $_} | sort | select -last 1)
$series = $null;$temp_graph = $null;$humid_graph = $null;$dewpt_graph = $null

$data | %{
$counter++
$series += @"
 <value xid="$counter">$($_.TIME)</value>

"@

 $temp_graph += @"
 <value xid="$counter">$($_.TEMP)</value>

"@

 $humid_graph += @"
 <value xid="$counter">$($_.HUMID)</value>

"@

 $dewpt_graph += @"
 <value xid="$counter">$($_.DEWPT)</value>

"@
}
$xml = $xml -replace "</series>","$series</series>"
$xml = $xml -replace "</graph>\r*\n*\s*<graph gid=`"1`"","$temp_graph</graph><graph gid=`"1`""
$xml = $xml -replace "</graph>\r*\n*\s*<graph gid=`"2`"","$humid_graph</graph><graph gid=`"2`""
$xml = $xml -replace "</graph>\r*\n*\s*</graphs>","$dewpt_graph</graph></graphs>"

$xml | out-file -encoding "UTF8" $xmlpath

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM