无法检索正确的节点数据

时间:2018-07-06 14:39:12

标签: xml powershell xpath edi

我正在尝试根据客户发送给我们的xml文件自动创建销售订单。

他们的XML文件的结构在不同的客户之间有所不同,因此我创建了一个SQL Server表,其中包含每个客户的基本订单信息路径。

$salesOrder包含整个XML文件。 将SQL数据加载到$customerTemplate中,并将订单行加载到名为$SalesOrderLines的数组中:

$salesOrderLines = @($salesOrder.SelectNodes($customerTemplate.LinePath))

问题是当我遍历订单行数组时,例如:

foreach ($salesOrderLine in $salesOrderLines) {
    $partCode = ($salesOrderLine.SelectSingleNode($customerTemplate.PartCodePath)).'#text'
}

它对于第一个订单行工作正常,即它选择了正确的零件代码,但对于任何后续订单行$partCode保持相同的值。即使我在循环结束时清除了$partCode变量,当它拾取第二个订单行时,$partCode也会从第一个订单行中获取值-尽管我可以看到$ orderLine包含正确的我正在寻找的属性。

我是否错过了一些明显的事情,因为在尝试解决此问题两天后,我没有取得太大进展吗?我可以根据需要提供整个脚本,但是我认为要求所有人检查300行代码实在太大了。

带有单个订单行的XML示例:

<?xml version="1.0"?>
<eExact xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="eExact-Schema.xsd">
    <Orders>
        <Order type="B" number="23298">
            <OrderedAt>
                <Creditor code="100001" number="100001" type="S">
                    <Name>Widget Co</Name>
                    <ExternalCode>EW001</ExternalCode>
                </Creditor>
                <Date>2018-01-31</Date>
            </OrderedAt>
            <OrderLine lineNo="1">
                <Description>Widget Sub Assy Std</Description>
                <Item code="12345" type="S" searchcode="">
                    <Description>Widget Sub Assy Std</Description>
                </Item>
                <Quantity>1</Quantity>
                <ItemCode>12345</ItemCode>
            </OrderLine>
        </Order>
    </Orders>
</eExact>

这是一个重现该问题的代码示例:

[xml]$salesOrder = Get-Content -Path "C:\Temp\PurchaseOrder.xml"

$salesOrderLines = @($salesOrder.SelectNodes("/eExact/Orders/Order/OrderLine"))
foreach ($salesOrderLine in $salesOrderLines) {
    $partCode = ($salesOrderLine.SelectSingleNode("//ItemCode")).'#text'
    $orderQty = ($salesOrderLine.SelectSingleNode("//Quantity")).'#text'
    $salesOrderLine.InnerXml
    "Part code = $partCode, Qty = $orderQty"
    Clear-Variable partCode, orderQty
}

以2行顺序显示,输出为:

<Description>Widget Sub Assy Std</Description><Item code="12345" type="S" searchcode=""><Description>Widget Sub Assy Std</Description></Item><Quantity>1</Quantity><ItemCode>12345</ItemCode>  
Part code = 12345, Qty = 1  
<Description>Big Widget</Description><Item code="54321" type="S" searchcode=""><Description>Big Widget</Description></Item><Quantity>3</Quantity><ItemCode>54321</ItemCode>  
Part code = 12345, Qty = 1

有了更多的订单行,我得到的第一零件编号和数量相同的重复次数更多。 我希望第二个订单行的输出是:

Part code = 54321, Qty = 3

1 个答案:

答案 0 :(得分:1)

用于选择<ItemCode><Quantity>节点的XPath表达式不正确。您正在正确的父节点上调用SelectSingleNode(),但是表达式不是相对于该节点的。 //表示根节点下方的任何位置,因此您始终选择XML文档中的第一个<ItemCode><Quantity>节点。

使表达式相对于当前节点(对于直接子节点为./,对于当前节点的任何后代为.//),代码将执行您想要的操作。另外,之后无需清除变量,因此只需删除Clear-Variable语句即可。也要删除分组括号。无需PowerShell代码看起来就像别人割指甲一样。

foreach ($salesOrderLine in $salesOrderLines) {
    $partCode = $salesOrderLine.SelectSingleNode('./ItemCode').'#text'
    $orderQty = $salesOrderLine.SelectSingleNode('./Quantity').'#text'
    "Part code = ${partCode}`nQty = ${orderQty}"
}