基于SQL查询数据在C#中通过循环生成订单XML(静态与循环结构)
用C# XDocument生成带动态订单行的XML文档
嘿,刚好我之前也做过类似的需求,用XDocument处理这种“静态部分+循环动态部分”的XML生成特别顺手,给你一步步拆解怎么实现:
核心思路
先把只需要出现一次的元素/属性(比如订单头、客户信息这些)先构建好,然后找到要容纳订单行的父节点,最后遍历你的订单行数据,逐个生成<OrderLine>元素并添加进去就行。
完整代码示例
假设你已经从SQL查询拿到了订单主数据和订单行的集合(这里用实体类模拟实际项目中的数据结构):
using System; using System.Collections.Generic; using System.Linq; using System.Xml.Linq; class OrderGenerator { static void Main() { // 模拟从SQL获取的订单主数据(只生成一次的部分) var orderHeader = new OrderHeader { OrderId = "ORD-2024-0012", CustomerName = "Alice Smith", OrderDate = DateTime.Now }; // 模拟从SQL获取的订单行数据(有N条就生成N个OrderLine) var orderLines = new List<OrderLine> { new OrderLine { ProductId = "PROD-100", Quantity = 2, UnitPrice = 29.99m }, new OrderLine { ProductId = "PROD-200", Quantity = 1, UnitPrice = 59.99m }, new OrderLine { ProductId = "PROD-300", Quantity = 3, UnitPrice = 9.99m } }; // 1. 构建XML基础静态结构 var orderDoc = new XDocument( new XDeclaration("1.0", "utf-8", "yes"), new XElement("Order", new XAttribute("OrderId", orderHeader.OrderId), new XElement("CustomerDetails", new XElement("Name", orderHeader.CustomerName), new XElement("OrderDate", orderHeader.OrderDate.ToString("yyyy-MM-dd")) ), // 预留订单行的父容器节点 new XElement("OrderItems") ) ); // 2. 找到订单行容器,循环添加动态订单行 var orderItemsContainer = orderDoc.Descendants("OrderItems").FirstOrDefault(); if (orderItemsContainer != null && orderLines.Any()) { foreach (var line in orderLines) { orderItemsContainer.Add( new XElement("OrderItem", new XElement("ProductId", line.ProductId), new XElement("Quantity", line.Quantity), new XElement("UnitPrice", line.UnitPrice.ToString("0.00")), new XElement("LineTotal", (line.Quantity * line.UnitPrice).ToString("0.00")) ) ); } } // 如果没有订单行,可以选择移除空的OrderItems节点 else if (orderItemsContainer != null) { orderItemsContainer.Remove(); } // 3. 输出XML或保存到文件 Console.WriteLine(orderDoc.ToString()); // orderDoc.Save(@"D:\Orders\ORD-2024-0012.xml"); } } // 实际项目中用实体类映射SQL返回的数据 public class OrderHeader { public string OrderId { get; set; } public string CustomerName { get; set; } public DateTime OrderDate { get; set; } } public class OrderLine { public string ProductId { get; set; } public int Quantity { get; set; } public decimal UnitPrice { get; set; } }
关键细节提醒
- 精准节点定位:用
Descendants("OrderItems").FirstOrDefault()可以灵活定位到目标父节点,不用硬编码XML层级结构,后续修改XML结构时更省心。 - 数据格式化:日期、金额这类数据要统一格式(比如日期用标准的
yyyy-MM-dd,金额保留两位小数),避免下游系统解析XML时出现异常。 - 空数据处理:如果订单行是空集合,可以选择移除
<OrderItems>节点,避免生成空的冗余节点,让XML更干净。 - 动态属性/元素:如果某些元素/属性需要按需生成(比如只有折扣的订单行才显示
<Discount>元素),可以在创建XElement时加条件判断:line.Discount > 0 ? new XElement("Discount", line.Discount) : null,XDocument会自动忽略null的元素/属性。
这样生成的XML会根据订单行的数量自动生成对应个数的<OrderItem>,静态部分只会出现一次,完全符合你的需求~
内容的提问来源于stack exchange,提问作者Iain
相关产品推荐
相关产品推荐

