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

ATM存款处理XML转CSV失败求助:仅生成标题无数据

How to Convert Complex ATM Deposit XML to CSV Correctly

I see you're struggling to convert that nested ATM XML to CSV—your regex approach is too fragile, and the XmlRecordReader setup had path/configuration issues. Let's break down what went wrong and fix it properly.

Why Your Previous Methods Failed

Method 1 (Regex-Based)

Regex is a terrible fit for parsing XML. XML has nested nodes, attributes, and self-closing tags that regex can't reliably interpret. Your patterns ended up stripping out all the actual attribute values (like machineId="4" or err="OK") when you removed the tags, leaving you with no data.

Method 2 (XmlRecordReader)

  • Your XPath was incorrect: "RemoteMessage/RemoteMessage" doesn't match your XML (there's only one root <RemoteMessage> node, no nested child with the same name). It should just be "RemoteMessage".
  • You didn't map the attributes from the nested <count> and <dev> nodes, so the reader had no data to pull into your CSV rows.

Working Solution: Use XDocument to Parse XML Properly

The right approach is to use .NET's XDocument (from System.Xml.Linq) to explicitly extract each piece of data from the XML structure, then build your CSV rows correctly. This handles nested nodes and attributes reliably.

Here's a complete, tested code example:

using System;
using System.IO;
using System.Xml.Linq;
using System.Linq;

class ATMXmlToCsvConverter
{
    static void Main(string[] args)
    {
        string xmlInputPath = @"C:\Users\Admin\Desktop\XMLMessage.xml";
        string csvOutputPath = @"C:\Users\Admin\Desktop\CSVMessage.csv";
        
        // Load and parse the XML document
        XDocument xmlDoc = XDocument.Load(xmlInputPath);
        var rootNode = xmlDoc.Element("RemoteMessage");
        
        if (rootNode == null)
        {
            Console.WriteLine("Error: Could not find root RemoteMessage node.");
            return;
        }
        
        // Extract core transaction attributes from the root node
        string operation = rootNode.Attribute("operation")?.Value ?? string.Empty;
        string deviceId = rootNode.Attribute("DeviceID")?.Value ?? string.Empty;
        string customerCode = rootNode.Attribute("CustomerCode")?.Value ?? string.Empty;
        string transactionDate = rootNode.Attribute("Date")?.Value ?? string.Empty;
        string transactionTime = rootNode.Attribute("Time")?.Value ?? string.Empty;
        string nop = rootNode.Attribute("NOP")?.Value ?? string.Empty;
        
        // Extract content/count details
        var countNode = rootNode.Element("content")?.Element("count");
        string contentMachineId = countNode?.Attribute("machineId")?.Value ?? string.Empty;
        string denomination = countNode?.Attribute("den")?.Value ?? string.Empty;
        string currency = countNode?.Attribute("curr")?.Value ?? string.Empty;
        string quantity = countNode?.Attribute("qty")?.Value ?? string.Empty;
        string noteType = countNode?.Attribute("type")?.Value ?? string.Empty;
        string nValue = countNode?.Attribute("N")?.Value ?? string.Empty;
        string sType = countNode?.Attribute("sType")?.Value ?? string.Empty;
        
        // Define CSV header (includes all fields we'll extract)
        string csvHeader = "Operation,DeviceID,CustomerCode,Date,Time,NOP,Content_MachineId,Denomination,Currency,Quantity,NoteType,N_Value,SType,Dev_Name,Dev_MachineId,Dev_Model,Dev_Status,Dev_DevS,Dev_Clean,Dev_Door,Dev_Bag,Dev_Cov,Dev_Blk,Dev_Ext";
        
        using (StreamWriter csvWriter = new StreamWriter(csvOutputPath))
        {
            csvWriter.WriteLine(csvHeader);
            
            // Process each device status entry (each gets its own CSV row)
            foreach (var devNode in rootNode.Element("devStatus")?.Elements("dev") ?? Enumerable.Empty<XElement>())
            {
                // Extract device attributes
                string devName = devNode.Attribute("name")?.Value ?? string.Empty;
                string devMachineId = devNode.Attribute("machineId")?.Value ?? string.Empty;
                string devModel = devNode.Attribute("mod")?.Value ?? string.Empty;
                string devErr = devNode.Attribute("err")?.Value ?? string.Empty;
                string devDevS = devNode.Attribute("devS")?.Value ?? string.Empty;
                string devClean = devNode.Attribute("clean")?.Value ?? string.Empty;
                string devDoor = devNode.Attribute("door")?.Value ?? string.Empty;
                string devBag = devNode.Attribute("bag")?.Value ?? string.Empty;
                string devCov = devNode.Attribute("cov")?.Value ?? string.Empty;
                string devBlk = devNode.Attribute("blk")?.Value ?? string.Empty;
                string devExt = devNode.Attribute("ext")?.Value ?? string.Empty;
                
                // Build the CSV row, escaping fields that need it
                string csvRow = $"{EscapeCsvField(operation)},{EscapeCsvField(deviceId)},{EscapeCsvField(customerCode)},{EscapeCsvField(transactionDate)},{EscapeCsvField(transactionTime)},{EscapeCsvField(nop)},{EscapeCsvField(contentMachineId)},{EscapeCsvField(denomination)},{EscapeCsvField(currency)},{EscapeCsvField(quantity)},{EscapeCsvField(noteType)},{EscapeCsvField(nValue)},{EscapeCsvField(sType)},{EscapeCsvField(devName)},{EscapeCsvField(devMachineId)},{EscapeCsvField(devModel)},{EscapeCsvField(devErr)},{EscapeCsvField(devDevS)},{EscapeCsvField(devClean)},{EscapeCsvField(devDoor)},{EscapeCsvField(devBag)},{EscapeCsvField(devCov)},{EscapeCsvField(devBlk)},{EscapeCsvField(devExt)}";
                
                csvWriter.WriteLine(csvRow);
            }
        }
        
        Console.WriteLine($"CSV file successfully created at: {csvOutputPath}");
    }
    
    // Helper method to escape CSV fields (handles commas, quotes, and special characters)
    private static string EscapeCsvField(string field)
    {
        if (field.Contains(",") || field.Contains("\"") || field.Contains("\n"))
        {
            return $"\"{field.Replace("\"", "\"\"")}\"";
        }
        return field;
    }
}

What This Code Does:

  1. Loads and parses the XML using XDocument, which properly handles nested nodes and attributes.
  2. Extracts all core data from the root <RemoteMessage> node, the <count> node, and each <dev> node in <devStatus>.
  3. Generates a CSV row for each device (since you have two devices in your XML, you'll get two rows), with the transaction and content data repeated for context.
  4. Escapes CSV fields to handle values with commas, quotes, or newlines, which is critical for valid CSV formatting.

Output CSV Example:

For your sample XML, the output will look like this:

Operation,DeviceID,CustomerCode,Date,Time,NOP,Content_MachineId,Denomination,Currency,Quantity,NoteType,N_Value,SType,Dev_Name,Dev_MachineId,Dev_Model,Dev_Status,Dev_DevS,Dev_Clean,Dev_Door,Dev_Bag,Dev_Cov,Dev_Blk,Dev_Ext
Device OK,SDM100-02378,12345,2020-09-06,14:30:10,3013,4,0.05,CHF,9,C,0,B,BDM,3,SDM 100S,KO,2,,,,,,
Device OK,SDM100-02378,12345,2020-09-06,14:30:10,3013,4,0.05,CHF,9,C,0,B,CDM,4,CDS 508 (BV DE0),OK,1,0,0,2,0,00000000,0

This gives you all the data from the XML in a structured, usable CSV format.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:00:02