Function Parameter System.Xml.XmlDocument gives error

I would like to create a script in which a function returns an XML document.
A second function should create a sub-element for the XML document which is later appended to the main XML document.
In my example, GenMainXML creates the main element and stores the data in the variable $NewXML. Then I want to use the second function GenSubXML to create and return an empty sub-element. To do this, I need the main element in the function, which I pass as a parameter. From then on, I always get the message:

    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

Here my TestCode

function GenMainXML(){
    $XMLDoc = New-Object -TypeName System.Xml.XmlDocument
    $null = $XMLDoc.AppendChild($XMLDoc.CreateXmlDeclaration('1.0', 'UTF-8', 'yes'));
    $XmlData = $XMLDoc.CreateElement("Data")
    $XMLDataConfig = $XMLDoc.CreateElement("Config")
    $XMLDataConfigVersion = $XMLDoc.CreateElement("Version")
    $XMLDataConfigVersion.InnerText = "1"
    $Null = $XMLDataConfig.AppendChild($XMLDataConfigVersion)
    $XMLDataConfigDataVersion = $XMLDoc.CreateElement("DataVersion")
    $XMLDataConfigDataVersion.InnerText = "1"
    $Null = $XMLDataConfig.AppendChild($XMLDataConfigDataVersion)
    $null = $XMLData.AppendChild($XMLDataConfig)
    $Null = $XMLDoc.AppendChild($XMLData)
    $xmldoc.InnerXml
    return $XMLDoc
}
function GenSubXML(){
    Param(
        # Parameter help description
        [Parameter(ValueFromPipelineByPropertyName,Mandatory = $true,
        HelpMessage = 'XML Object')]
        $XMLSource
        )
        write-host "GenSubXML"
        $XMLSource.InnerXml
        $XMLTitle=  $XMLSource.CreateElement("Title")
        $Null = $XMLTitle.AppendChild($XMLSource.CreateElement("ID"))
        $Null = $XMLTitle.AppendChild($XMLSource.CreateElement("Title"))
        $Null = $XMLTitle.AppendChild($XMLSource.CreateElement("ExtraTitle"))
        return $XMLTitle
}
$NewXML = GenMainXML
$NewSubXML = GenSubXML -XMLSource $NewXML
$NewXML.Data.AppendChild($NewSubXML)

Hello. I’m unable to determine what your question is. Please help us help you.

I think you may have inadvertently withheld some useful information. When loading your functions and executing them as you described, this is actually the complete error text:

Method invocation failed because [System.String] does not contain a method named 'CreateElement'.
At line:10 char:9
+         $XMLTitle=  $XMLSource.CreateElement("Title")
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound
 
Method invocation failed because [System.String] does not contain a method named 'CreateElement'.
At line:11 char:9
+         $Null = $XMLTitle.AppendChild($XMLSource.CreateElement("ID"))
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

Method invocation failed because [System.String] does not contain a method named 'CreateElement'.
At line:12 char:9
+         $Null = $XMLTitle.AppendChild($XMLSource.CreateElement("Title ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

Method invocation failed because [System.String] does not contain a method named 'CreateElement'.
At line:13 char:9
+         $Null = $XMLTitle.AppendChild($XMLSource.CreateElement("Extra ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : MethodNotFound

It would appear at first glance this is because once you define $XMLSource it is a string object rather than XML. This looks like it’s because your first function GenMainXML is returning an array of string text rather than an XML object.
If I change the parameter on your second function to strongly type the input as XML:

Param(
        # Parameter help description
        [Parameter(ValueFromPipelineByPropertyName,Mandatory = $true,
        HelpMessage = 'XML Object')]
        [XML]$XMLSource
        )

It fails with a different error providing another clue

GenSubXML : Cannot process argument transformation on parameter 'XMLSource'. Cannot convert value "System.Object[]" to type "System.Xml.XmlDocument". Error: "The specified node cannot be inserted as the 
valid child of this node, because the specified node is the wrong type."
At line:1 char:35
+ $NewSubXML = GenSubXML -XMLSource $NewXML
+                                   ~~~~~~~
    + CategoryInfo          : InvalidData: (:) [GenSubXML], ParameterBindingArgumentTransformationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,GenSubXML

The issue is with the last two lines of your GenMainXML:

    $xmldoc.InnerXml
    return $XMLDoc

your function returns two objects. String text, followed by your XML object. This means you end up with an array of objects for output, which ruins what your other function is expecting.

This code now executes without error. Whether or not it does what you intended I’m not sure:

function GenMainXML(){
    $XMLDoc = New-Object -TypeName System.Xml.XmlDocument
    $null = $XMLDoc.AppendChild($XMLDoc.CreateXmlDeclaration('1.0', 'UTF-8', 'yes'));
    $XmlData = $XMLDoc.CreateElement("Data")
    $XMLDataConfig = $XMLDoc.CreateElement("Config")
    $XMLDataConfigVersion = $XMLDoc.CreateElement("Version")
    $XMLDataConfigVersion.InnerText = "1"
    $Null = $XMLDataConfig.AppendChild($XMLDataConfigVersion)
    $XMLDataConfigDataVersion = $XMLDoc.CreateElement("DataVersion")
    $XMLDataConfigDataVersion.InnerText = "1"
    $Null = $XMLDataConfig.AppendChild($XMLDataConfigDataVersion)
    $null = $XMLData.AppendChild($XMLDataConfig)
    $Null = $XMLDoc.AppendChild($XMLData)
    return $XMLDoc
}
function GenSubXML(){
    Param(
        # Parameter help description
        [Parameter(ValueFromPipelineByPropertyName,Mandatory = $true,
        HelpMessage = 'XML Object')]
        $XMLSource
        )
        write-host "GenSubXML"
        $XMLTitle=  $XMLSource.CreateElement("Title")
        $Null = $XMLTitle.AppendChild($XMLSource.CreateElement("ID"))
        $Null = $XMLTitle.AppendChild($XMLSource.CreateElement("Title"))
        $Null = $XMLTitle.AppendChild($XMLSource.CreateElement("ExtraTitle"))
        return $XMLTitle
}
$NewXML = GenMainXML
$NewSubXML = GenSubXML -XMLSource $NewXML
$NewXML.Data.AppendChild($NewSubXML)

It was a mistake on my part. I had the values ​​output in the function without a write host and forgot that this would automatically return the value. Thank you.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.