I have variable $purchaseOrdersTemplate outside of my foreach. When the line to AppendChild to the $purchaseOrder variable runs the item xml is being appended to both $purchaseOrder and $purchaseOrderTemplate. I would expect that it should not modify the template variable. Can I please get an explanation of this? For now I am putting the template variable in the first foreach so that it is reset each order but I think it looks weird to have it there.
foreach ($order in $groupOrders) {
$purchaseOrder = $purchaseOrderTemplate
$purchaseOrder.PurchaseOrderNew.InputParameter.PurchaseOrders.PurchaseOrder.OrderID = $order.Name
foreach($orderItem in $order.Group) {
$purchaseOrderItem = $purchaseOrderItemTemplate
$purchaseOrderItem.PurchaseOrderItem.ItemOrderID = $orderItem.ItemArray[1]
$purchaseOrderItem = $purchaseOrder.ImportNode($purchaseOrderItem.PurchaseOrderItem,$true)
[void]$purchaseOrder.SelectSingleNode('/PurchaseOrderNew/InputParameter/PurchaseOrders/PurchaseOrder/PurchaseOrderItems').AppendChild($purchaseOrderItem)
}
}
Olaf
November 5, 2021, 8:09pm
2
I don’t know if anyone here speaks fluently XML but I’d expect that some sample data may help understanding your issue and playing around to find a solution.
Of course
[xml]$purchaseOrderTemplate = @"
<PurchaseOrderNew>
<InputParameter>
<PurchaseOrders>
<PurchaseOrder>
<OrderId>PO</OrderId>
<PurchaseOrderItems />
</PurchaseOrder>
</PurchaseOrders>
</InputParameter>
</PurchaseOrderNew>
"@
[xml]$purchaseOrderItemTemplate = @"
<PurchaseOrderItem>
<ItemOrderID />
</PurchaseOrderItem>
"@
$groupOrders = $packageItems.Tables.Rows | Group-Object -Property OrderId
foreach ($order in $groupOrders) {
$purchaseOrder = $purchaseOrderTemplate
# $purchaseOrder.PurchaseOrderNew.InputParameter.PurchaseOrders.PurchaseOrder.OrderID = $order.Name
foreach($orderItem in $order.Group) {
write-host $orderItem.ItemArray
$purchaseOrderItem = $purchaseOrderItemTemplate
# $purchaseOrderItem.PurchaseOrderItem.ItemOrderID = $orderItem.ItemArray[1]
$purchaseOrderItem = $purchaseOrder.ImportNode($purchaseOrderItem.PurchaseOrderItem,$true)
[void]$purchaseOrder.SelectSingleNode('/PurchaseOrderNew/InputParameter/PurchaseOrders/PurchaseOrder/PurchaseOrderItems').AppendChild($purchaseOrderItem)
}
}
I’m sorry but I don’t know how to provide sample data for $packageItems. It is a dataset. But, when I tried to create sample data using another format for posting the problem seemed to go away so maybe that helps to understand the problem.
[xml]$purchaseOrderTemplate = @"
<PurchaseOrderNew>
<InputParameter>
<PurchaseOrders>
<PurchaseOrder>
<OrderId>PO</OrderId>
<PurchaseOrderItems />
</PurchaseOrder>
</PurchaseOrders>
</InputParameter>
</PurchaseOrderNew>
"@
[xml]$purchaseOrderItemTemplate = @"
<PurchaseOrderItem>
<ItemOrderID />
</PurchaseOrderItem>
"@
$orders = @"
OrderId,Customer,Item
4567,jsmith@company.org,Shoes 10.5
4570,tommy@anothercomp.com,Shirt XL
4567,jsmith@company.org,Shirt XL
4561,sally@company.org,Pants Small
4567,jsmith@company.org,Pant XL
"@ | ConvertFrom-Csv
$groupOrders = $orders | Group-Object -Property OrderId
foreach ($order in $groupOrders) {
$purchaseOrder = $purchaseOrderTemplate
# $purchaseOrder.PurchaseOrderNew.InputParameter.PurchaseOrders.PurchaseOrder.OrderID = $order.Name
foreach($orderItem in $order.Group) {
write-host $orderItem.ItemArray
$purchaseOrderItem = $purchaseOrderItemTemplate
# $purchaseOrderItem.PurchaseOrderItem.ItemOrderID = $orderItem.ItemArray[1]
$purchaseOrderItem = $purchaseOrder.ImportNode($purchaseOrderItem.PurchaseOrderItem,$true)
[void]$purchaseOrder.SelectSingleNode('/PurchaseOrderNew/InputParameter/PurchaseOrders/PurchaseOrder/PurchaseOrderItems').AppendChild($purchaseOrderItem)
}
}
Olaf
November 5, 2021, 9:37pm
4
Sorry, I still did not get what you’re actually trying to do.
You could limit it to a few data sets and use Export-CliXML to export it into an XML formatted string.
So the problem might be caused by your input data.
Could you post a small sample of the expected result unsing your sample data?
flenwan
November 5, 2021, 10:44pm
5
I will post data Monday. The expectation is that the Template xml should not be getting modified. The code inserts the item xml node into the order xml which is what it should do, but it is also inserting it into the template xml so that the next time the template is used it has previous item nodes that should not be there.
Olaf
November 5, 2021, 11:03pm
6
flenwan:
I will post data Monday.
… cool … I’m looking forward to it …
Hope this is what you are looking for… The data comes from a parameterized query,
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="0">
<TN RefId="0">
<T>System.Data.SqlClient.SqlParameter</T>
<T>System.Data.Common.DbParameter</T>
<T>System.MarshalByRefObject</T>
<T>System.Object</T>
</TN>
<ToString>@dateshipped</ToString>
<Props>
<Obj N="CompareInfo" RefId="1">
<TN RefId="1">
<T>System.Data.SqlTypes.SqlCompareOptions</T>
<T>System.Enum</T>
<T>System.ValueType</T>
<T>System.Object</T>
</TN>
<ToString>None</ToString>
<I32>0</I32>
</Obj>
<S N="XmlSchemaCollectionDatabase"></S>
<S N="XmlSchemaCollectionOwningSchema"></S>
<S N="XmlSchemaCollectionName"></S>
<B N="ForceColumnEncryption">false</B>
<Obj N="DbType" RefId="2">
<TN RefId="2">
<T>System.Data.DbType</T>
<T>System.Enum</T>
<T>System.ValueType</T>
<T>System.Object</T>
</TN>
<ToString>DateTime</ToString>
<I32>6</I32>
</Obj>
<I32 N="LocaleId">0</I32>
<S N="ParameterName">@dateshipped</S>
<By N="Precision">0</By>
<By N="Scale">0</By>
<Obj N="SqlDbType" RefId="3">
<TN RefId="3">
<T>System.Data.SqlDbType</T>
<T>System.Enum</T>
<T>System.ValueType</T>
<T>System.Object</T>
</TN>
<ToString>DateTime</ToString>
<I32>4</I32>
</Obj>
<Obj N="SqlValue" RefId="4">
<TN RefId="4">
<T>System.Data.SqlTypes.SqlDateTime</T>
<T>System.ValueType</T>
<T>System.Object</T>
</TN>
<ToString>11/3/2021 8:42:21 AM</ToString>
<Props>
<B N="IsNull">false</B>
<DT N="Value">2021-11-03T08:42:21.42</DT>
<I32 N="DayTicks">44501</I32>
<I32 N="TimeTicks">9402426</I32>
</Props>
</Obj>
<S N="UdtTypeName"></S>
<S N="TypeName"></S>
<DT N="Value">2021-11-03T08:42:21.42</DT>
<Obj N="Direction" RefId="5">
<TN RefId="5">
<T>System.Data.ParameterDirection</T>
<T>System.Enum</T>
<T>System.ValueType</T>
<T>System.Object</T>
</TN>
<ToString>Input</ToString>
<I32>1</I32>
</Obj>
<B N="IsNullable">false</B>
<I32 N="Offset">0</I32>
<I32 N="Size">0</I32>
<S N="SourceColumn"></S>
<B N="SourceColumnNullMapping">false</B>
<Obj N="SourceVersion" RefId="6">
<TN RefId="6">
<T>System.Data.DataRowVersion</T>
<T>System.Enum</T>
<T>System.ValueType</T>
<T>System.Object</T>
</TN>
<ToString>Current</ToString>
<I32>512</I32>
</Obj>
</Props>
</Obj>
<I32>3</I32>
<Obj RefId="7">
<TN RefId="7">
<T>System.Data.DataSet</T>
<T>System.ComponentModel.MarshalByValueComponent</T>
<T>System.Object</T>
</TN>
<ToString>System.Data.DataSet</ToString>
<Props>
<Obj N="RemotingFormat" RefId="8">
<TN RefId="8">
<T>System.Data.SerializationFormat</T>
<T>System.Enum</T>
<T>System.ValueType</T>
<T>System.Object</T>
</TN>
<ToString>Xml</ToString>
<I32>0</I32>
</Obj>
<Obj N="SchemaSerializationMode" RefId="9">
<TN RefId="9">
<T>System.Data.SchemaSerializationMode</T>
<T>System.Enum</T>
<T>System.ValueType</T>
<T>System.Object</T>
</TN>
<ToString>IncludeSchema</ToString>
<I32>1</I32>
</Obj>
<B N="CaseSensitive">false</B>
<Obj N="DefaultViewManager" RefId="10">
<TN RefId="10">
<T>System.Data.DataViewManager</T>
<T>System.ComponentModel.MarshalByValueComponent</T>
<T>System.Object</T>
</TN>
<LST>
<Obj RefId="11">
<TN RefId="11">
<T>System.Data.DataViewManagerListItemTypeDescriptor</T>
<T>System.Object</T>
</TN>
<ToString>System.Data.DataViewManagerListItemTypeDescriptor</ToString>
</Obj>
</LST>
</Obj>
<B N="EnforceConstraints">true</B>
<S N="DataSetName">NewDataSet</S>
<S N="Namespace"></S>
<S N="Prefix"></S>
<Obj N="ExtendedProperties" RefId="12">
<TN RefId="12">
<T>System.Data.PropertyCollection</T>
<T>System.Collections.Hashtable</T>
<T>System.Object</T>
</TN>
<DCT />
</Obj>
<B N="HasErrors">false</B>
<B N="IsInitialized">true</B>
<Obj N="Locale" RefId="13">
<TN RefId="13">
<T>System.Globalization.CultureInfo</T>
<T>System.Object</T>
</TN>
<ToString>en-US</ToString>
<Props>
<I32 N="LCID">1033</I32>
<S N="Name">en-US</S>
<S N="DisplayName">English (United States)</S>
<S N="IetfLanguageTag">en-US</S>
<S N="ThreeLetterISOLanguageName">eng</S>
<S N="ThreeLetterWindowsLanguageName">ENU</S>
<S N="TwoLetterISOLanguageName">en</S>
</Props>
</Obj>
<Nil N="Site" />
<Obj N="Relations" RefId="14">
<TN RefId="14">
<T>System.Data.DataRelationCollection+DataSetRelationCollection</T>
<T>System.Data.DataRelationCollection</T>
<T>System.Data.InternalDataCollectionBase</T>
<T>System.Object</T>
</TN>
<IE />
<Props>
<I32 N="Count">0</I32>
<B N="IsReadOnly">false</B>
<B N="IsSynchronized">false</B>
<Ref N="SyncRoot" RefId="14" />
</Props>
</Obj>
<Obj N="Tables" RefId="15">
<TN RefId="15">
<T>System.Data.DataTableCollection</T>
<T>System.Data.InternalDataCollectionBase</T>
<T>System.Object</T>
</TN>
<IE>
<Obj RefId="16">
<TN RefId="16">
<T>System.Data.DataTable</T>
<T>System.ComponentModel.MarshalByValueComponent</T>
<T>System.Object</T>
</TN>
<IE>
<Obj RefId="17">
<TN RefId="17">
<T>System.Data.DataRow</T>
<T>System.Object</T>
</TN>
<ToString>System.Data.DataRow</ToString>
<Props>
<I32 N="ID">4</I32>
<S N="OrderNumber">1548</S>
<S N="TrackingNo">456</S>
<DT N="DateShipped">2021-11-04T00:00:00</DT>
<Db N="Weight">6</Db>
<D N="Cost">5.5000</D>
<S N="AccountNumber"></S>
<S N="ServiceType">GRND</S>
<S N="Carrier">ACME</S>
<I64 N="OrderId">399</I64>
<B N="processed">false</B>
</Props>
</Obj>
<Obj RefId="18">
<TNRef RefId="17" />
<ToString>System.Data.DataRow</ToString>
<Props>
<I32 N="ID">5</I32>
<S N="OrderNumber">1547</S>
<S N="TrackingNo">456</S>
<DT N="DateShipped">2021-11-04T00:00:00</DT>
<Db N="Weight">6</Db>
<D N="Cost">5.5000</D>
<S N="AccountNumber"></S>
<S N="ServiceType">GRND</S>
<S N="Carrier">ACME</S>
<I64 N="OrderId">398</I64>
<B N="processed">false</B>
</Props>
</Obj>
<Obj RefId="19">
<TNRef RefId="17" />
<ToString>System.Data.DataRow</ToString>
<Props>
<I32 N="ID">6</I32>
<S N="OrderNumber">1547</S>
<S N="TrackingNo">456</S>
<DT N="DateShipped">2021-11-04T00:00:00</DT>
<Db N="Weight">6</Db>
<D N="Cost">5.5000</D>
<S N="AccountNumber"></S>
<S N="ServiceType">GRND</S>
<S N="Carrier">ACME</S>
<I64 N="OrderId">398</I64>
<B N="processed">false</B>
</Props>
</Obj>
</IE>
<Props>
<B N="CaseSensitive">false</B>
<B N="IsInitialized">true</B>
<S N="RemotingFormat">Xml</S>
<Obj N="ChildRelations" RefId="20">
<TN RefId="18">
<T>System.Data.DataRelationCollection+DataTableRelationCollection</T>
<T>System.Data.DataRelationCollection</T>
<T>System.Data.InternalDataCollectionBase</T>
<T>System.Object</T>
</TN>
<IE />
</Obj>
<Obj N="Columns" RefId="21">
<TN RefId="19">
<T>System.Data.DataColumnCollection</T>
<T>System.Data.InternalDataCollectionBase</T>
<T>System.Object</T>
</TN>
<IE>
<S>ID</S>
<S>OrderNumber</S>
<S>TrackingNo</S>
<S>DateShipped</S>
<S>Weight</S>
<S>Cost</S>
<S>AccountNumber</S>
<S>ServiceType</S>
<S>Carrier</S>
<S>OrderId</S>
<S>processed</S>
</IE>
</Obj>
<Obj N="Constraints" RefId="22">
<TN RefId="20">
<T>System.Data.ConstraintCollection</T>
<T>System.Data.InternalDataCollectionBase</T>
<T>System.Object</T>
</TN>
<IE />
</Obj>
<S N="DataSet">System.Data.DataSet</S>
<Obj N="DefaultView" RefId="23">
<TN RefId="21">
<T>System.Data.DataView</T>
<T>System.ComponentModel.MarshalByValueComponent</T>
<T>System.Object</T>
</TN>
<LST>
<S>System.Data.DataRowView</S>
<S>System.Data.DataRowView</S>
<S>System.Data.DataRowView</S>
</LST>
</Obj>
<S N="DisplayExpression"></S>
<Obj N="ExtendedProperties" RefId="24">
<TNRef RefId="12" />
<DCT />
</Obj>
<B N="HasErrors">false</B>
<Ref N="Locale" RefId="13" />
<I32 N="MinimumCapacity">50</I32>
<Obj N="ParentRelations" RefId="25">
<TNRef RefId="18" />
<IE />
</Obj>
<Obj N="PrimaryKey" RefId="26">
<TN RefId="22">
<T>System.Data.DataColumn[]</T>
<T>System.Array</T>
<T>System.Object</T>
</TN>
<LST />
</Obj>
<Obj N="Rows" RefId="27">
<TN RefId="23">
<T>System.Data.DataRowCollection</T>
<T>System.Data.InternalDataCollectionBase</T>
<T>System.Object</T>
</TN>
<IE>
<Ref RefId="17" />
<Ref RefId="18" />
<Ref RefId="19" />
</IE>
</Obj>
<S N="TableName">Table</S>
<S N="Namespace"></S>
<S N="Prefix"></S>
<Nil N="Site" />
<Nil N="Container" />
<B N="DesignMode">false</B>
<B N="ContainsListCollection">false</B>
</Props>
</Obj>
</IE>
<Props>
<I32 N="Count">1</I32>
<B N="IsReadOnly">false</B>
<B N="IsSynchronized">false</B>
<Ref N="SyncRoot" RefId="15" />
</Props>
</Obj>
<Nil N="Container" />
<B N="DesignMode">false</B>
<B N="ContainsListCollection">true</B>
</Props>
</Obj>
</Objs>
When you execute this command
$purchaseOrder = $purchaseOrderTemplate
You are linking these objects. $purchaseOrder is just a reference to the template, not a copy. You should clone it instead
$purchaseOrder = $purchaseOrderTemplate.Clone()
Now when you modify $purchaseOrder it won’t affect the template.
Great, thank you krzydoug. And thank you as well, Olaf.