I am writing a powershell script to create a xml file which i later feed into azure pipeline. Issue is this generate an encoded output with < , > being converted, which is not in a correct xml format I understand this is related to automatic encoding. Some help to prevent this is appreciated
$myitems =
@([pscustomobject]
@{AssertName="Joe";TestPass=$true;},
[pscustomobject]
@{AssertName="Sue";TestPass=$false;},
[pscustomobject]
@{AssertName="Cat";TestPass=$true;})
Set-Content $path <?xml version="1.0"?><testsuites></testsuites>'
$xml = New-Object XML
$xml.Load($path)
$element = $xml.SelectSingleNode("testsuites")
$innerText=""
foreach ($item in $myitems )
{
$innerText=$innerText '<testsuite errors="0" failures="0" id="0" name="$item.AssertName" tests="1"><testcase classname="some.class.name" name="Test1" time="123.345000"/></testsuite>'
}
[xml] $xml = Get-Content -Raw $path
$xml.testsuites = $innerText
$xml.Save($path)
CodePudding user response:
One way to do this is to use an XmlWriter
to build up your document element by element. The XmlWriter
automatically takes care of the encoding.
$path = "$PSScriptRoot\test.xml"
$myitems = @(
[pscustomobject] @{AssertName="Joe";TestPass=$true}
[pscustomobject] @{AssertName="Sue";TestPass=$false}
[pscustomobject] @{AssertName="Cat";TestPass=$true}
)
$writerSettings = [Xml.XmlWriterSettings] @{
Encoding = [Text.Encoding]::UTF8
Indent = $true
IndentChars = "`t"
WriteEndDocumentOnClose = $true # Write document end tag automatically
}
$writer = [xml.XmlWriter]::Create( $path, $writerSettings )
$writer.WriteStartDocument() # writes the XML declaration
$writer.WriteStartElement('testsuites')
foreach ($item in $myitems )
{
# Indentation is used to show the nesting of the XML elements
$writer.WriteStartElement('testsuite')
$writer.WriteAttributeString('errors', 0)
$writer.WriteAttributeString('failures', 0)
$writer.WriteAttributeString('id', 0)
$writer.WriteAttributeString('name', $item.AssertName)
$writer.WriteAttributeString('tests', 1)
$writer.WriteStartElement('testcase')
$writer.WriteAttributeString('classname', 'some.class.name')
$writer.WriteAttributeString('name', 'Test1')
$writer.WriteAttributeString('time', '123.345000')
$writer.WriteEndElement()
$writer.WriteEndElement()
}
# Very important - writes document end tag and closes the file
$writer.Dispose()
Output:
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
<testsuite errors="0" failures="0" id="0" name="Joe" tests="1">
<testcase classname="some.class.name" name="Test1" time="123.345000" />
</testsuite>
<testsuite errors="0" failures="0" id="0" name="Sue" tests="1">
<testcase classname="some.class.name" name="Test1" time="123.345000" />
</testsuite>
<testsuite errors="0" failures="0" id="0" name="Cat" tests="1">
<testcase classname="some.class.name" name="Test1" time="123.345000" />
</testsuite>
</testsuites>
CodePudding user response:
The way to do this is create an new xml document from your string and import the concerned node (ImportNode
) in the main document and than append the child (AppendChild
) to the specific node:
$myitems =
@{ AssertName="Joe"; TestPass=$true },
@{ AssertName="Sue"; TestPass=$false },
@{ AssertName="Cat"; TestPass=$true }
$Main = [xml]'<?xml version="1.0"?><testsuites></testsuites>'
foreach ($item in $myitems) {
$String = '<testsuite errors="0" failures="0" id="0" name="' $item.AssertName '" tests="1"><testcase classname="some.class.name" name="Test1" time="123.345000"/></testsuite>'
$Xml = [xml]$String
$Node = $Main.ImportNode($Xml.testsuite, $True)
$Null = $Main.SelectSingleNode('testsuites').AppendChild($Node)
}
[System.Xml.Linq.XDocument]::Parse($Main.OuterXml).ToString()
<testsuites>
<testsuite errors="0" failures="0" id="0" name="Joe" tests="1">
<testcase classname="some.class.name" name="Test1" time="123.345000" />
</testsuite>
<testsuite errors="0" failures="0" id="0" name="Sue" tests="1">
<testcase classname="some.class.name" name="Test1" time="123.345000" />
</testsuite>
<testsuite errors="0" failures="0" id="0" name="Cat" tests="1">
<testcase classname="some.class.name" name="Test1" time="123.345000" />
</testsuite>
</testsuites>