Reputation: 23
I'm trying to create an xml document using PowerShell, my issue is that the elements that have been appended to a parent, do not inherit the declare namespace prefix, however whilst playing around, I have managed to get it have the prefix but only with it including another xmlns="".
$UserName = $env:UserName
$OutputPath = "C:\Users\" + $UserName +"\Desktop\Generator\Output\"
$OutputXML = $OutputPath + "Test_File_1.xml"
#Namespace URIs
$VQ5NSX = "http://example2"
$VQ5INTX ="http://example1"
[xml]$Doc = New-Object System.Xml.XmlDocument
$dec = $Doc.CreateXmlDeclaration("1.0","UTF-8",$null)
$doc.AppendChild($dec)
$root = $doc.CreateNode("element","ns:responsefile", $VQ5NSX)
$int = $doc.CreateNode("element", "int:IntegrationHeader",$VQ5INTX)
$IntDt = $doc.CreateElement("int:Date",$null)
$IntDt.InnerText = "Date Text"
$Int.AppendChild($IntDt) | Out-Null
$IntId = $doc.CreateElement("Identification")
$IntAppID = $doc.CreateElement("ApplicationId")
$IntAppIDtxt = $Doc.CreateTextNode("App Id Text")
$IntAppId.AppendChild($IntAppIDtxt)|Out-Null
$IntId.AppendChild($IntAppID)|Out-Null
$IntTransID = $doc.CreateElement("TransactionId")
$IntTransIDtxt = $Doc.CreateTextNode("Tran Id Text")
$IntTransID.AppendChild($IntTransIDtxt) |Out-Null
$IntId.AppendChild($IntTransID) |Out-Null
$Int.AppendChild($IntId) |Out-Null
$root.AppendChild($int)|Out-Null
$Res = $doc.CreateNode("element","ns:ResponseItem", $null)
$ItemDetail = $doc.CreateElement("ns:Item1")
$ItemDetail = $doc.CreateTextNode("Item one text")
$Res.AppendChild($ItemDetail)|Out-Null
$root.AppendChild($res)|Out-Null
$doc.AppendChild($root) |Out-Null
$doc.save($OutputXML)
This generates the following output;
<?xml version="1.0" encoding="UTF-8"?>
<ns:responsefile xmlns:ns="http://example2">
<int:IntegrationHeader xmlns:int="http://example1">
<Date>Date Text</Date>
<Identification>
<ApplicationId>App Id Text</ApplicationId>
<TransactionId>Tran Id Text</TransactionId>
</Identification>
</int:IntegrationHeader>
<ResponseItem>Item one text</ResponseItem>
</ns:responsefile>
However I need it to generate this output;
<?xml version="1.0" encoding="UTF-8"?>
<ns:responsefile xmlns:ns="http://example2">
<int:IntegrationHeader xmlns:int="http://example1">
<int:Date>Date Text</Date>
<int:Identification>
<int:ApplicationId>App Id Text</int:ApplicationId>
<int:TransactionId>Tran Id Text</int:TransactionId>
</int:Identification>
</int:IntegrationHeader>
<ns:ResponseItem>Item one text</ns:ResponseItem>
</ns:responsefile>
Any help would be most appreciated!
Upvotes: 2
Views: 2073
Reputation: 200193
For working with namespaced XML use a namespace manager.
[xml]$doc = @'
<?xml version="1.0" encoding="UTF-8"?>
<ns:responsefile xmlns:ns="http://example2">
<int:IntegrationHeader xmlns:int="http://example1">
</int:IntegrationHeader>
<ResponseItem>Item one text</ResponseItem>
</ns:responsefile>
'@
$int_ns = 'http://example1'
$nsm = New-Object Xml.XmlNamespaceManager($doc.NameTable)
$nsm.AddNamespace('int', $int_ns)
Create the new element in the intended namespace before appending it to the parent node:
$Int = $doc.SelectSingleNode('//int:IntegrationHeader', $nsm)
$IntDt = $doc.CreateElement('int', 'Date', $int_ns)
$IntDt.InnerText = "Date Text"
$Int.AppendChild($IntDt) | Out-Null
Upvotes: 1
Reputation: 97658
Although the definition of the prefix can be inherited by the child nodes, each child node still needs to be specified as in that namespace.
Currently, you are explicitly requesting that the <Date>
element is not in any namespace:
$doc.CreateElement("int:Date",$null)
The .net class is assuming you put the int:
in by mistake, because an element in no namespace has no prefix.
Instead, you need to specify that the <Date>
element is in the http://example1
namespace:
$doc.CreateElement("int:Date",$VQ5INTX)
If the implementation is smart, it will notice that the prefix int
is already bound to that namespace, and avoid repeating the xmlns:int
attribute (which would be untidy, but not change the document significantly).
Upvotes: 1