Преобразование файла CSV в соответствующий формат XML - PullRequest
1 голос
/ 27 марта 2019

Я пытаюсь вставить некоторые файлы CSV с разделителями табуляции в XML через PowerShell, и я изо всех сил пытаюсь понять все это.Я на 100% уверен, что это что-то очень простое, что мне не хватает, так что помощь будет очень цениться.Я очень близок, но просто не могу преодолеть последнее препятствие.

Я хочу, чтобы этот скрипт перебирал CSV с разделителями табуляции, на который он указывает ($path), убирая каждую строку изCSV и поместите данные в лист XML ($xmlpath).

Пример CSV:

"Name"  "Item"  "Purchase Price"
"Jimmy Smits"   "Egg"   "£40"
"Edward Price"  "KumQuat"   "£6000"
"Timmy Mallet"  "Bug"   "£2"
"Edgar Allen Poe"   "Weird" "0"
"2Pac Shakur"   "Eggnog"    ""

Пример шаблона вывода XML:

<registration>
    <Individual>
        <Name></Name>
        <Item></Item>
        <Purchase Price></Purchase Price>
    </Individual>
</registration>

И этото, о чем я суетился с

$data = Import-Csv -Path $path -Delimiter "`t"

$xmlnames = $data | Select-Object "Name"
$xmlitems = $data | Select-Object "Item"
$xmlprice = $data | Select-Object "Purchase Price"

$entryTemplate = @'
<individual>
    <Name>$($xmlnames.Name)</Name>
    <Item>$($xmlitems.Item)</Item>
    <Purchase Price>$($xmlprice."Purchase Price")</Purchase Price>
</individual>
'@

$xml = $data | ForEach-Object {
    $ExecutionContext.InvokeCommand.ExpandString($entrytemplate)
}
$xml | Out-File $xmlpath

, который затем выдает;

<Individual>
    <Name>Jimmy Smits Edward Price Timmy Mallet Edgar Allen Poe 2Pac Shakur</Name>
    <Item>System.Object IList.Item(int index) {get;set;}</Item>
    <Purchase Price>£40 £6000 £2 0 </Purchase Price>
</Individual>

Так что где-то я тупо путаюсь с двумя вещами;

  1. * * $data | Select-Object 'thing' дает мне весь список «вещей», а не перебирает каждую из «вещей» и перечисляет их по одному на каждую запись XML.Тем не менее, дает ли мне правильное количество записей?
  2. Мои «Элементы» перечислены как системные объекты (не значения), несмотря на то, что ко всем остальным относятся одинаково.

Ответы [ 2 ]

2 голосов
/ 27 марта 2019

Три оператора

$xmlnames = $data | Select-Object "Name"
$xmlitems = $data | Select-Object "Item"
$xmlprice = $data | Select-Object "Purchase Price"

дают вам списки пользовательских объектов только с одним свойством.Используя эти списки в вашем шаблоне, вы вставляете все значения в тег с каждой итерацией.То, что вы хотите, это просто значение текущей итерации, поэтому создание списков раньше не принесет вам никакой пользы.Что вам действительно нужно, так это текущий объект во время каждой итерации цикла.

В случае $xmlitems вы также сталкиваетесь с проблемой PowerShell, потому что переменные $xmlnames, $xmlitems и $xmlprice являются массивами.При использовании точечного доступа к массиву PowerShell выполняет то, что называется перечисление члена .По сути, $xmlnames.Name не даст вам значение свойства Name объекта array , но значение свойства Name всего массива elements .

Перечисление членов работает, только если сам объект массива не имеет члена с таким именем.Что возвращает нас к $xmlitems.Для этой переменной вы пытаетесь получить значение свойства Item элементов массива.Однако объект массива на самом деле имеет метод Item(), поэтому $xmlitems.Item пытается вызвать этот метод вместо свойства Item элементов массива.Но поскольку метод перегружен и в вызове отсутствуют круглые скобки ($xmlitems.Item вместо $xmlitems.Item()), вместо этого PowerShell покажет вам определение метода.

Удалите операторы Select-Object и замените переменные массива в XMLшаблон фрагмента с переменной «текущий объект» $_ и код будет делать то, что вы хотите.

$entryTemplate = @'
<individual>
    <Name>$($_.Name)</Name>
    <Item>$($_.Item)</Item>
    <Purchase Price>$($_."Purchase Price")</Purchase Price>
</individual>
'@
1 голос
/ 27 марта 2019

Вы также можете использовать «LINQ to XML» для создания XML.

using namespace "System.Xml.Linq"
Add-Type -AssemblyName System.Xml.Linq

[XElement]::new("registration", @(
    Import-Csv -Path $path -Delimiter "`t" | foreach {
        [XElement]::new("Individual",
            [XElement]::new("Name", $_.Name),
            [XElement]::new("Item", $_.Item),
            [XElement]::new("PurchasePrice", $_."Purchase Price"))
    }
)).Save($xmlpath)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...