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

如何用C#获取XML二级节点内容并转换PowerShell函数为C#

解决C# PowerShell二进制模块获取XML二级节点的问题

我明白你现在的需求:要在C#写的PowerShell二进制模块里,实现和Invoke-Transform完全一样的功能——解析XML中<m:properties>下的属性名和值,同时解决节点导航和类型转换的问题。下面给你一步步梳理解决方案:

先明确核心需求对应的逻辑

你的PowerShell函数本质是:遍历输入的XmlElement数组,逐个导航到content -> m:properties节点,然后把properties下的每个子节点(去掉命名空间前缀)作为属性名,节点文本作为值,输出成PowerShell可识别的自定义对象。

C#实现完整代码示例

首先要注意XML命名空间的处理(因为m:前缀对应特定的命名空间URI,必须映射才能找到节点),然后用正确的方式转换节点类型、构建输出对象:

using System;
using System.Management.Automation;
using System.Xml;
using System.Linq;

namespace MyPowerShellModule
{
    [Cmdlet(VerbsLifecycle.Invoke, "Transform")]
    [OutputType(typeof(PSObject))]
    public class InvokeTransformCommand : Cmdlet
    {
        [Parameter(Mandatory = true, ValueFromPipeline = true)]
        public XmlElement[] Records { get; set; }

        protected override void ProcessRecord()
        {
            // 替换成你实际XML中m:前缀对应的命名空间URI(从xmlns:m属性获取)
            XmlNamespaceManager nsManager = new XmlNamespaceManager(new NameTable());
            nsManager.AddNamespace("m", "http://schemas.microsoft.com/ado/2007/08/dataservices/metadata");

            foreach (XmlElement record in Records)
            {
                // 模拟PowerShell中的 ($record).content 导航
                XmlElement contentNode = record.SelectSingleNode("./content") as XmlElement;
                if (contentNode == null)
                {
                    WriteWarning("当前record节点未找到content子节点");
                    continue;
                }

                // 模拟PowerShell中的 ($record).content.properties 导航,这里必须用命名空间管理器
                XmlElement propertiesNode = contentNode.SelectSingleNode("./m:properties", nsManager) as XmlElement;
                if (propertiesNode == null)
                {
                    WriteWarning("content节点下未找到m:properties子节点");
                    continue;
                }

                // 构建和PowerShell PSCustomObject等价的输出对象
                PSObject outputObj = new PSObject();

                // 遍历properties下的所有XmlElement子节点(过滤掉文本、注释等非元素节点)
                foreach (XmlElement propNode in propertiesNode.ChildNodes.Cast<XmlNode>().Where(n => n is XmlElement))
                {
                    // 用LocalName去掉命名空间前缀(比如m:Id变成Id)
                    string propName = propNode.LocalName;
                    string propValue = propNode.InnerText;

                    // 给输出对象添加属性
                    outputObj.Properties.Add(new PSNoteProperty(propName, propValue));
                }

                // 输出结果,PowerShell中会像原生对象一样处理
                WriteObject(outputObj);
            }
        }
    }
}

关键问题的解决说明

  1. 命名空间处理:带前缀的XML节点(比如m:properties)必须通过XmlNamespaceManager映射对应的URI才能被找到,你需要把代码中的URI替换成你实际XML里的xmlns:m属性值。
  2. XmlNode转XmlElement:
    • 用as XmlElement做安全转换,避免强制转换抛出异常;
    • 用Cast<XmlNode>().Where(n => n is XmlElement)过滤掉非元素类型的节点(比如空白文本节点),和PowerShell中ChildNodes | Where-Object { $_ -is [XmlElement] }的逻辑一致。
  3. 模拟PowerShell链式访问:
    • record.SelectSingleNode("./content")对应$record.content;
    • contentNode.SelectSingleNode("./m:properties", nsManager)对应$record.content.properties,完全还原PowerShell的节点导航逻辑。
  4. 输出对象匹配:用PSObject配合PSNoteProperty构建的对象,在PowerShell中可以直接用Select-Object、Format-Table等命令处理,和原生PSCustomObject效果一致。

测试验证

编译这个模块导入PowerShell后,执行类似以下命令就能得到和Invoke-Transform一样的结果:

$xml = [xml](Get-Content .\your-example.xml)
$xml.root.record | Invoke-Transform

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 20:37:32