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

求助:如何将指定XML转换为格式化纯文本?附C#尝试代码

解决方案:将XML转换为格式化键值对文本

当然可以实现这个转换需求!你的现有代码只抓取了gls:PatientDem元素的整体拼接文本,没有深入遍历它内部的嵌套子元素,所以才得不到你想要的PatientId: 123455, IdScheme: TEST这类精准的键值对格式。下面是修正后的代码,以及详细的逻辑说明:

问题分析

你原来的代码使用x.Value获取gls:PatientDem的文本,这会把该元素下所有子元素的文本内容直接拼接成一串,完全丢失了各个字段的结构信息。要实现预期格式,我们需要递归遍历XML的所有元素,找到每个叶子节点(没有子元素的节点),然后提取它的层级名称作为键,文本内容作为值。

修正后的C#代码

using System;
using System.Text;
using System.Xml.Linq;

public class XmlToKeyValueConverter
{
    public static void Main()
    {
        // 你的XML内容(这里直接嵌入方便测试)
        string xml = @"<?xml version=""1.0""?>
<gls:TheDocument xmlns:pbr=""http://www.something.com"" xmlns:gls=""http://www.testsomething.com"" xmlns:cnr=""http://www.organisation.com"" xmlns:h=""http://www.w3.org/1999/xhtml"" xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" schemaVersion=""2.8"">
<gls:PatientDem>
<cnr:PatientId>
<cnr:IdValue>123455</cnr:IdValue>
<cnr:IdScheme>TEST</cnr:IdScheme>
<cnr:IdType>PRN</cnr:IdType>
</cnr:PatientId>
<cnr:PatientName>
<cnr:Name>
<cnr:Title>Mr</cnr:Title>
<cnr:GivenName>Joe</cnr:GivenName>
<cnr:FamilyName>Wood</cnr:FamilyName>
</cnr:Name>
<cnr:NameType>Current Name</cnr:NameType>
</cnr:PatientName>
<cnr:PatientAddress>
<cnr:Address>
<cnr:AddressLine>57 High Street</cnr:AddressLine>
<cnr:AddressLine>London</cnr:AddressLine>
</cnr:Address>
<cnr:PostCode>WC1E 7HU</cnr:PostCode>
<cnr:AddressType>Current Residence</cnr:AddressType>
</cnr:PatientAddress>
<cnr:DateOfBirth>1969-11-02</cnr:DateOfBirth>
<cnr:Sex>M</cnr:Sex>
</gls:PatientDem>
<pbr:PatientAdminRef>
<pbr:Referrer>
<pbr:RefGP>
<cnr:GpcpName>
<cnr:FullName>DR SMITH</cnr:FullName>
</cnr:GpcpName>
<cnr:TheOrganisation>
<cnr:OrganisationId>
<cnr:IdValue>52522</cnr:IdValue>
<cnr:IdScheme>PracticeID</cnr:IdScheme>
<cnr:IdType>Healthcare Organisation</cnr:IdType>
</cnr:OrganisationId>
<cnr:OrganisationName>National Health Service</cnr:OrganisationName>
<cnr:OrganisationAddress>
<cnr:TheAddress>
<cnr:AddressLine1>Centre House</cnr:AddressLine1>
<cnr:AddressLine2>799 Chichester Street</cnr:AddressLine2>
<cnr:AddressLine3>London</cnr:AddressLine3>
</cnr:TheAddress>
<cnr:AddressType>Practice Address</cnr:AddressType>
</cnr:OrganisationAddress>
<cnr:OrganisationTelecom>
<cnr:TelephoneNumber>016190542350</cnr:TelephoneNumber>
<cnr:TeleType>Voice</cnr:TeleType>
</cnr:OrganisationTelecom>
</cnr:TheOrganisation>
</pbr:RefGP>
</pbr:Referrer>
</pbr:PatientAdminRef>
</gls:TheDocument>";

        XDocument doc = XDocument.Parse(xml);
        XElement root = doc.Root;
        XNamespace glsNs = root.GetNamespaceOfPrefix("gls");
        XNamespace cnrNs = root.GetNamespaceOfPrefix("cnr");
        XNamespace pbrNs = root.GetNamespaceOfPrefix("pbr");

        var output = new StringBuilder();

        // 处理患者 demographic 信息
        ProcessNestedElements(doc.Descendants(glsNs + "PatientDem").First(), output, "");
        // 处理转诊信息
        ProcessNestedElements(doc.Descendants(pbrNs + "PatientAdminRef").First(), output, "");

        // 输出结果(你也可以把output.ToString()写入文件或返回)
        Console.WriteLine(output.ToString());
    }

    /// <summary>
    /// 递归处理嵌套XML元素,提取键值对
    /// </summary>
    /// <param name="element">当前处理的XML元素</param>
    /// <param name="sb">用于构建输出的StringBuilder</param>
    /// <param name="parentKeyPrefix">父元素的键前缀(用于生成层级键名)</param>
    private static void ProcessNestedElements(XElement element, StringBuilder sb, string parentKeyPrefix)
    {
        string elementLocalName = element.Name.LocalName;
        // 生成当前元素的键名(包含父层级,避免重复键)
        string currentKey = string.IsNullOrEmpty(parentKeyPrefix) 
            ? elementLocalName 
            : $"{parentKeyPrefix}.{elementLocalName}";

        // 如果当前元素有子元素,递归处理子元素
        if (element.Elements().Any())
        {
            foreach (var childElement in element.Elements())
            {
                ProcessNestedElements(childElement, sb, currentKey);
            }
        }
        else
        {
            // 如果是叶子节点(没有子元素),输出键值对
            sb.AppendLine($"{currentKey}: {element.Value}");
        }
    }
}

代码说明

  1. 递归遍历逻辑:ProcessNestedElements方法会逐层深入XML结构,遇到叶子节点(没有子元素的节点)时,就将其层级化的键名和文本值添加到输出中。
  2. 命名空间处理:正确获取了XML中的各个命名空间(gls、cnr、pbr),确保能精准定位到目标元素。
  3. 层级键名:生成的键名包含父元素路径(比如PatientDem.PatientId.IdValue),避免了重复键名的问题(比如XML中出现两次AddressLine)。

可选调整

如果你不想保留父层级前缀,只想显示最后一级的键名(比如直接显示IdValue: 123455而不是PatientDem.PatientId.IdValue: 123455),可以修改ProcessNestedElements方法的currentKey生成逻辑,只使用elementLocalName即可:

// 修改这一行,去掉父前缀
string currentKey = elementLocalName;

不过这种方式可能会出现重复键名(比如两个AddressLine),需要根据你的需求权衡选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 05:14:21