Reputation: 892
I have a text file with this content:
123asdf
abdfeef
22343sf
dfafdsf
The content of this file is changing.
I want to create an xml file, where one element contains the text file content.
I tried this, but all the content is in the same element:
$Getfile = Get-Content .\DeleteFile.txt
$TimeStamp = [System.TimeZoneInfo]::ConvertTimeBySystemTimeZoneId(
(Get-Date), 'Taipei Standard Time')
$delete_file = @"
<?xml version="1.0" encoding="UTF-8"?>
<Handling>
<Deleted>
<1>$Getfile</1>
</Deleted>
<TimeStamp>$TimeStamp</TimeStamp>
</Handling>
"@
$delete_file | Out-File .\DeleteFile.xml
Output:
<?xml version="1.0" encoding="UTF-8"?>
<Handling>
<Deleted>
<1>123asdf abdfeef 22343sf dfafdsf</1>
</Deleted>
<TimeStamp>12/04/2019 17:49:06</TimeStamp>
</Handling>
My expectation was that the output would be like this:
<?xml version="1.0" encoding="UTF-8"?>
<Handling>
<Deleted>
<1>123asdf</1>
<2>abdfeef</2>
<3>22343sf</3>
<4>dfafdsf</4>
</Deleted>
<TimeStamp>12/04/2019 17:49:06</TimeStamp>
</Handling>
Can anyone help me please?
Upvotes: 1
Views: 677
Reputation: 437753
vonPryz' helpful answer leverages the .NET XmlDocument
API to construct the document.
A solution using an expandable string (string interpolation), as you've attempted, is possible, namely by including statements that enumerate the $Getfile
array and construct numbered XML elements from its elements, via $(...)
, the sub-expression operator.
Two caveats:
XML element names must not start with a digit, so trying to create elements named 1
, 2
, ... will result in an invalid XML document. Therefore, the code below uses e1
, e2
, ... instead.
The code uses Set-Content -Encoding Utf8
to save the output file, so as to ensure that the character encoding used - UTF-8 - matches the encoding specified in the XML declaration (encoding="UTF-8"
).
Out-File
/ >
would result in UTF-16LE encoding instead.Set-Content -Encoding Utf8
creates a UTF-8 file with a BOM, unlike in PowerShell [Core] v6+. In Windows PowerShell, you cannot opt out of the BOM; in PowerShell [Core] v6+, you can opt in with -Encoding utf8BOM
.$Getfile = "123asdf", "abdfeef", "22343sf", "dfafdsf" # sample input
$delete_file = @"
<?xml version="1.0" encoding="UTF-8"?>
<Handling>
<Deleted>
$(
$i = 0
$(foreach ($el in $GetFile) {
++$i
" <e$i>$el</e$i>"
}) -join [Environment]::NewLine
)
</Deleted>
<TimeStamp>$TimeStamp</TimeStamp>
</Handling>
"@
$delete_file | Set-Content -Encoding Utf8 .\DeleteFile.xml
Upvotes: 2
Reputation: 24071
The contents go into same element, as you are not creating new XML elements. To add elements, create a XML object and use its CreateElement
and AppendChild
methods. Like so,
# Skeleton document that is filled later
[xml]$d = @'
<Handling>
<Deleted />
<TimeStamp />
</Handling>
'@
# Dummy data, read these from a file instead
$data = @('123asdf', 'abdfeef', '22343sf', 'dfafdsf')
# XPath selects the node under which new elements are added
$n = $d.SelectSingleNode('/Handling/Deleted')
# Loop through input data
for($i=0; $i -lt $data.length; ++$i) {
# Create new element, Element name is from loop counter
$e = $d.CreateElement(($i+1).ToString())
$e.InnerText = $data[$i]
# Add the new node into document
$n.AppendChild($e) | out-null
}
# Display the results.
$d.save([console]::out)
Output:
<?xml version="1.0" encoding="ibm850"?>
<Handling>
<Deleted>
<1>123asdf</1>
<2>abdfeef</2>
<3>22343sf</3>
<4>dfafdsf</4>
</Deleted>
<TimeStamp />
</Handling>
Upvotes: 3