Author Posts

July 22, 2014 at 10:24 am

Trying to insert a node from a template into a loaded XML document. I'm getting the following error:

Exception calling "AppendChild" with "1" argument(s): "The specified node cannot be inserted as the valid child of this node
, because the specified node is the wrong type."

The end goal would be to add a {param} with {name}Blah{/name} with a for loop. If the XML has an existing parameter, I can clone that and do a for loop, but if no child node exists I would like to copy a node from a template and then I assume it would be just cloning. I cannot, however, figure out how to insert the node from the template:

[xml]$template = '
    {param}
	    {name}{/name}
        {other}{/other}
   {/param}
'

[xml]$xmlExample = @"
{?xml version="1.0"?}
{job}
    {parameters}
    {/parameters}
{/job}
"@

$jobParameters = $xmlExample.SelectSingleNode("//parameters")
$jobParameters.AppendChild($template.Clone())

Also, to make this as "real world" as possible, the XML does not even have an opening parameter tag. So, the file I'm working with look more like:

[xml]$xmlExample = @"
{?xml version="1.0"?}
{job}
{/parameters}
{/job}
"@

which Powershell doesn't like with this error.

Error: "The 'job' start tag on line 2 position 2 does not match the end tag of 
'parameters'. Line 3, position 7."

I'm just trying to get to this:

{?xml version="1.0"?}
{job}
    {parameters}
        {param}
	        {name}{/name}
            {other}{/other}
       {/param}
    {/parameters}
{/job}

Edit: Website eats XML, so replaced standard tags with {}

July 22, 2014 at 10:34 am

Try this:

$jobParameters = $xmlExample.SelectSingleNode("//parameters")
$null = $jobParameters.AppendChild($xmlExample.ImportNode($template.param, $true))

Couple of things here. You can't append an element that came from a different Document object, but that's what the ImportNode method is for. Also, you can't import a Document ([xml]), but you can import a node from within that document, such as $template.param .

July 22, 2014 at 11:00 am

@dave, That did work. Thank you for the quick turn around. Any insight on the XML tag that doesn't start. I see a lot of tags that do it in this XML and get the aforementioned error. Granted, I can open the file and do a simple replace, but didn't know if there was a preferred method with XML dom. Thank you again.

July 22, 2014 at 11:03 am

I'm not sure what you're talking about. The XML you posted with no opening parameters tag is invalid, and I haven't come across this in any documents. You do, on the other hand, frequently see self-closing tags like this:

{parameters /} 

instead of

 {parameters}{/parameters}

July 23, 2014 at 6:14 am

Thanks for you assistance. The self closing tags are similar to HTML. Last question (for this post), I see numerous methods to nullify the output from methods

$null = $jobParameters.AppendChild($xmlExample.ImportNode($template.param, $true))
#or
[void]$jobParameters.AppendChild($xmlExample.ImportNode($template.param, $true))
#or
$jobParameters.AppendChild($xmlExample.ImportNode($template.param, $true)) | Out-Null

The all accomplish the same thing, but does one work better or preferred over the other?

July 23, 2014 at 6:22 am

They do all accomplish the same thing, but piping to Out-Null is much slower than the other two. I tend to use assignments to $null, but that's just personal preference. If you cast to [void], sometimes you have to put an extra set of parentheses around the pipeline that's producing the results, whereas sticking "$null = " at the beginning of a pipeline always works.