使用linq到xml按元素展平XML结构

时间:2012-02-09 19:49:15

标签: c# xml linq-to-xml xml-parsing

我最近创建了一篇关于展平XML结构的帖子,因此每个元素及其值都转换为根元素的属性。得到了一些很好的答案,让它运作起来。然而,令人遗憾的是,通过展平,客户意味着压扁元素而不是将它们变成属性: - /

我拥有的是:

<members>
    <member xmlns="mynamespace" id="1" status="1">
       <sensitiveData>
           <notes/>
           <url>someurl</url>
           <altUrl/>
           <date1>somedate</date1>
            <date2>someotherdate</date2>
            <description>some description</description>
            <tags/>
            <category>some category</category>
        </sensitiveData>
        <contacts>
            <contact contactId="1">
                <contactPerson>some contact person</contactPerson>
                <phone/>
                <mobile>mobile number</mobile>
                <email>some@email.com</email>
            </contact>
        </kontakter>
    </member>
</members>

我需要的是以下内容:

<members>
    <member xmlns="mynamespace" id="1" status="1">
        <sensitiveData/>
        <notes/>
        <url>someurl</url>
        <altUrl/>
        <date1>somedate</date1>
        <date2>someotherdate</date2>
        <description>some description</description>
        <tags/>
        <category>some category</category>
        <contacts/>
        <contact contactId="1"></contact>
        <contactPerson>some contact person</contactPerson>
        <phone/>
        <mobile>mobile number</mobile>
        <email>some@email.com</email>
    </member>
</members>

所以基本上所有元素,但作为子节点扁平化。我知道开始解析像这样的XML文档并不是很好,但它基本上是唯一的选择,因为CMS导入数据需要这种扁平结构,而XML文档来自外部Web服务。

我开始为此做一个递归方法,但我有一种奇怪的感觉,它可以使得一些LINQ to XML(?)我可以更顺畅(好吧,至少尽可能平滑)最好的linq到xml,所以我希望那里有人会帮助提示如何解决这个问题? : - )

非常感谢任何帮助/提示!

提前致谢。

/博

1 个答案:

答案 0 :(得分:2)

这似乎有效 - 可能会有更简洁的方法:

var doc = XDocument.Load("test.xml");
XNamespace ns = "mynamespace";
var member = doc.Root.Element(ns + "member");

// This will *sort* of flatten, but create copies...
var descendants = member.Descendants().ToList();

// So we need to strip child elements from everywhere...
// (but only elements, not text nodes). The ToList() call
// materializes the query, so we're not removing while we're iterating.
foreach (var nested in descendants.Elements().ToList())
{
    nested.Remove();
}
member.ReplaceNodes(descendants);