C# 使用c将XML转换为CSV而不使用xslt

C# 使用c将XML转换为CSV而不使用xslt,c#,xml,csv,C#,Xml,Csv,我一直在网络上搜索,我想一定有人在我之前就需要这个,并且做得更好,以实现xml到csv的转换。我有一个非常标准的xml,如下所示: <ArrayOfDealer xmlns:i="http://www.w3.org/2001/XMLSchema-instance"> <Dealer> <Cmf>76066699</Cmf> <DealerNumber/> <Dealershi

我一直在网络上搜索,我想一定有人在我之前就需要这个,并且做得更好,以实现xml到csv的转换。我有一个非常标准的xml,如下所示:

<ArrayOfDealer xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    <Dealer>
        <Cmf>76066699</Cmf>
        <DealerNumber/>
        <DealershipName>BROWARD MOTORSPORTS - WPB</DealershipName>
    </Dealer>
    <Dealer>
        <Cmf>76071027</Cmf>
        <DealerNumber/>
        <DealershipName>BROWARD MOTORSPORTS OF FT LAUDERDALE LLC</DealershipName>
    </Dealer>
    <Dealer>
        <Cmf>76014750</Cmf>
        <DealerNumber/>
        <DealershipName>Jet Ski of Miami</DealershipName>
    </Dealer>
    <Dealer>
        <Cmf>76066987</Cmf>
        <DealerNumber/>
        <DealershipName>BROWARD MOTORSPORTS - Davie</DealershipName>
    </Dealer>
</ArrayOfDealer>
XML来自于我存储为字符串的api

想法


编辑:为了澄清这一点,我知道该结构将与上述类似,没有进一步的节点嵌套,但实际的标记名可能非常有用。

使用将xml反序列化为对象。然后使用所讨论的方法将对象序列化为csv文件

这样的东西能满足您的需要吗:

Func<string, string> csvFormat =
    t => String.Format("\"{0}\"", t.Replace("\"", "\"\""));

var xml = XDocument.Parse(/* xml text here */);

Func<XDocument, IEnumerable<string>> getFields =
    xd =>
        xd
            .Descendants("Dealer")
            .SelectMany(d => d.Elements())
            .Select(e => e.Name.ToString())
            .Distinct();

var headers =
    String.Join(",",
        getFields(xml)
            .Select(f => csvFormat(f)));

var query =
    from dealer in xml.Descendants("Dealer")
    select string.Join(",",
        getFields(xml)
            .Select(f => dealer.Elements(f).Any()
                ? dealer.Element(f).Value
                : "")
            .Select(x => csvFormat(x)));

var csv =
    String.Join(Environment.NewLine,
        new [] { headers }.Concat(query));

这仍然假设结构是相同的,但下面的字段可能会更改。

这很粗糙,但只要结构保持不变,它将创建CSV文件或制表符分隔的文本文件

Root -> Main Element (for each row) -> Child Elements (any number)
我包含了两个不同的XML测试集,因此您可以正确地看到生成的结果

工作样本:

Unicorn.csv:

UnicornColor,Cmf,UnicornNumber,UnicornshipName
Red,76066699,,BROWARD MOTORSPORTS - WPB,
Red,76071027,,BROWARD MOTORSPORTS OF FT LAUDERDALE LLC,
Red,76014750,,Jet Ski of Miami,
Red,76066987,,BROWARD MOTORSPORTS - Davie,
Unicorn.txt选项卡分隔:

UnicornColor    Cmf         UnicornNumber   UnicornshipName
Red             76066699                    BROWARD MOTORSPORTS - WPB           
Red             76071027                    BROWARD MOTORSPORTS OF FT LAUDERDALE LLC    
Red             76014750                    Jet Ski of Miami                
Red             76066987                    BROWARD MOTORSPORTS - Davie         

下面的代码以一种通用的方式将问题提供的简单xml内容转换为csv格式的字符串头+行序列,在下面的示例中,只需要实现一个更可靠的函数来转义值标识转换

string csvSeparator = ",";
Func<string, string> escapeValue = val => val;

string xml = "xml content";
XDocument doc = XDocument.Parse(xml);

var headers = doc.Root
                .Elements()
                .First()
                .Elements()
                .Select(el => el.Name.LocalName);

var headerRow = string.Join(csvSeparator, headers);

var rows = from el in doc.Root.Elements()
            let values = from prop in el.Elements()
                        select escapeValue(prop.Value)
            let row = string.Join(csvSeparator, values)
            select row;


IEnumerable<string> csvLines = new[] { headerRow }.Concat(rows);

不知道命名约定会成为这种方法的一个问题吗?我写的东西必须对标记的名称保持沉默,所以您永远不会知道xml的结构?您将无法生成架构文件?我知道结构将与上述类似,没有进一步的节点嵌套,但实际的标记名可能非常复杂。@ZachM。我已经将你的评论从这个答案编辑到你的问题中。在您的问题中包含此类相关信息总是一个好主意,以获得最适用的答案;你能至少确保结构是相同的吗?也就是说,你知道根目录下有一个重复节点,其中包含相同数量的子节点,这些子节点将成为csv值?是的,这就是我的意思,是的,结构将是相同的。结果,必须是正确的CSV逗号分隔或制表符分隔的文本文件?这取决于元素的名称,OP在注释中声明的元素名称他不会知道,也不会是常量。@DavidKhaykin-我已相应地更新了我的解决方案。如果OP编辑了他的问题以澄清这一点,那就太好了。最后的问题和答案应该匹配,不需要阅读评论。我同意这一点。作为更有经验的会员,我们可以随时将他们的评论编辑到问题中,并留下评论,说明未来的礼仪。我本来打算这么做的,但后来我开始喝酒开玩笑…@DavidKhaykin-有时候喝酒是最容易的选择-
UnicornColor,Cmf,UnicornNumber,UnicornshipName
Red,76066699,,BROWARD MOTORSPORTS - WPB,
Red,76071027,,BROWARD MOTORSPORTS OF FT LAUDERDALE LLC,
Red,76014750,,Jet Ski of Miami,
Red,76066987,,BROWARD MOTORSPORTS - Davie,
UnicornColor    Cmf         UnicornNumber   UnicornshipName
Red             76066699                    BROWARD MOTORSPORTS - WPB           
Red             76071027                    BROWARD MOTORSPORTS OF FT LAUDERDALE LLC    
Red             76014750                    Jet Ski of Miami                
Red             76066987                    BROWARD MOTORSPORTS - Davie         
string csvSeparator = ",";
Func<string, string> escapeValue = val => val;

string xml = "xml content";
XDocument doc = XDocument.Parse(xml);

var headers = doc.Root
                .Elements()
                .First()
                .Elements()
                .Select(el => el.Name.LocalName);

var headerRow = string.Join(csvSeparator, headers);

var rows = from el in doc.Root.Elements()
            let values = from prop in el.Elements()
                        select escapeValue(prop.Value)
            let row = string.Join(csvSeparator, values)
            select row;


IEnumerable<string> csvLines = new[] { headerRow }.Concat(rows);
string csvContent = string.Join(Environment.NewLine, csvLines);