You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何移除XML元素中的xsi:nil属性以正常处理PowerShell数据?

问题:处理SOAP返回XML中带xsi:nil属性的元素异常

从SOAP服务器获取的XML结果里,部分<data>元素带有xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"属性,导致数据处理异常。使用Select-Xml能正常处理多数元素,但对带该属性的<data>元素无效。

XML示例

<ns2:getReportResultResponse xmlns:ns2="http://service.admin.ws.example.com/">
  <return>
    <header>
      <values>
        <data>DATE</data>
        <data>AGENT</data>
        <data>AGENT FIRST NAME</data>
        <data>AGENT LAST NAME</data>
        <data>CALLS count</data>
        <data>HANDLE TIME</data>
        <data>AFTER CALL WORK TIME</data>
        <data>CONFERENCE TIME</data>
        <data>SHORT CALLS count</data>
        <data>LONG CALLS count</data>
      </values>
    </header>
    <records>
      <values>
        <data>2022/07/27</data>
        <data>example@example.com</data>
        <data>Test</data>
        <data>User</data>
        <data>49</data>
        <data>02:00:00</data>
        <data>00:45:00</data>
        <data xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
        <data>49</data>
        <data>0</data>
      </values>
    </records>
  </return>
</ns2:getReportResultResponse>

原PowerShell代码

Select-Xml -Content ([xml]$final_response | Select-Object -ExpandProperty Objects | Select-Object -ExpandProperty Object | Select-Object -ExpandProperty '#text') "//return/*/values" -Namespace @{ ns = 'http://service.admin.ws.example.com/'} |
  ForEach-Object {
    # See if an entry already exists for the key at hand.
    if ($obj.Contains($_.Node.header.values.data)) {
      # Convert the entry value into an array on demand and 
      # append the value at hand.
      [array] $obj[$_.Node.header.values.data] += $_.Node.records.values.data
    }
    else {
      # Create the entry, using the value as-is.
      $obj[$_.Node.header.values.data] = $_.Node.records.values.data
    }
  }

注:$final_response即上述XML示例输出。


解决方案

核心问题

带xsi:nil="true"的<data>是空自闭合标签,直接访问.values.data时,PowerShell会忽略这类节点,导致数组长度不匹配、值缺失或错位。

修正后的代码

# 直接解析XML对象
$xml = [xml]$final_response

# 提取header的所有字段名
$headers = $xml.SelectNodes('//header/values/data') | ForEach-Object { $_.InnerText }

# 提取records的所有值,处理空节点
$recordValues = $xml.SelectNodes('//records/values/data') | ForEach-Object {
    # 判断是否为xsi:nil空节点
    if ($_.HasAttribute('xsi:nil') -and $_.GetAttribute('xsi:nil') -eq 'true') {
        ""  # 空节点替换为空字符串,可根据需求改为0或其他默认值
    } else {
        $_.InnerText
    }
}

# 构建结果哈希表(保持顺序)
$obj = [ordered]@{}
for ($i=0; $i -lt $headers.Count; $i++) {
    $key = $headers[$i]
    $value = $recordValues[$i]
    
    if ($obj.Contains($key)) {
        [array]$obj[$key] += $value
    } else {
        $obj[$key] = $value
    }
}

# 输出结果
$obj

关键改进点

  1. 直接解析XML对象,避免原代码中冗余的Select-Object操作和无效的命名空间配置
  2. 显式遍历所有<data>节点,强制处理空节点,保证字段值和header一一对应,不会错位
  3. 使用[ordered]哈希表保持字段顺序和XML中header的顺序一致

内容的提问来源于stack exchange,提问作者Rod Argumedo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 12:24:19