如何使用LINQ to Xml用单个父节点替换多个父节点?

时间:2013-12-05 05:19:12

标签: c# xml linq

我正在使用以下代码从列表中生成XML,

var xEle = new XElement("DataDictionary",
               from emp in factDetails
               select new XElement(emp.ElementPrefix.Contains("dei") ? "filingInfo" : "TaggableContent",
                          new XElement(p.GetParameterType(emp.ElementType,emp.ElementPrefix),
                              new XElement("xbrlElementInfo",
                                  new XAttribute("name", emp.ElementName),
                                  new XElement("ContentValue", emp.FactValue)
 ))));



//Function to Get the Element Name.
public string GetParameterType(string p, string prefix)
{
    if (prefix.Contains("dei"))
    {
        return "filingItem";
    }
    else
    {
        if (p.Contains("TABLE"))
            return "cell";
        else
        {
            return "paragraph";
        }
    }
}

当前输出,因为我正在使用基于列值( emp.ElementPrefix )的三元运算,所以为每个Xelement生成父节点,而不是创建一个父节点而不是多个节点父节点:

<?xml version="1.0" encoding="utf-8"?>
<DataDictionary>
  <filingInfo>
    <filingItem>
      <xbrlElementInfo name="DocumentType">
        <ContentValue>485BPOS</ContentValue>
      </xbrlElementInfo>
    </filingItem>
  </filingInfo>
  <filingInfo>
    <filingItem>
      <xbrlElementInfo name="DocumentPeriodEndDate">
        <ContentValue>2013-06-30</ContentValue>
      </xbrlElementInfo>
    </filingItem>
  </filingInfo>
    <TaggableContent>
    <cell>
      <xbrlElementInfo name="AcquiredFundFeesAndExpensesOverAssets">
        <ContentValue>0.0001</ContentValue>
      </xbrlElementInfo>
    </cell>
  </TaggableContent>
  <TaggableContent>
    <cell>
      <xbrlElementInfo name="AcquiredFundFeesAndExpensesOverAssets">
        <ContentValue>0.0001</ContentValue>
      </xbrlElementInfo>
    </cell>
  </TaggableContent>
</DataDictionary>

预期输出:(<filingInfo> & <TaggableContent>应该是父节点,而不是为每个元素创建子节点),如下所示,

<?xml version="1.0" encoding="utf-8"?>
<DataDictionary>
  <filingInfo>
    <filingItem>
      <xbrlElementInfo name="DocumentType">
        <ContentValue>485BPOS</ContentValue>
      </xbrlElementInfo>
    </filingItem>
    <filingItem>
      <xbrlElementInfo name="DocumentPeriodEndDate">
        <ContentValue>2013-06-30</ContentValue>
      </xbrlElementInfo>
    </filingItem>
  </filingInfo>
    <TaggableContent>
    <cell>
      <xbrlElementInfo name="AcquiredFundFeesAndExpensesOverAssets">
        <ContentValue>0.0001</ContentValue>
      </xbrlElementInfo>
    </cell>      
    <cell>
      <xbrlElementInfo name="AcquiredFundFeesAndExpensesOverAssets">
        <ContentValue>0.0001</ContentValue>
      </xbrlElementInfo>
    </cell>
  </TaggableContent>
</DataDictionary>

1 个答案:

答案 0 :(得分:2)

您正在为每个不可数项创建整个xml层次结构, 在预期产出中有分组值。

有两种方法可以实现:

两个单独的查询:

var fillingIngo = 
    from emp in factDetails
    where emp.ElementPrefix.Contains("dei")
    select new XElement(p.GetParameterType(emp.ElementType,emp.ElementPrefix),
                new XElement("xbrlElementInfo",
                    new XAttribute("name", emp.ElementName),
                    new XElement("ContentValue", emp.FactValue)));

var taggableContent = 
    from emp in factDetails
    where !emp.ElementPrefix.Contains("dei")
    select new XElement(p.GetParameterType(emp.ElementType,emp.ElementPrefix),
            new XElement("xbrlElementInfo",
                new XAttribute("name", emp.ElementName),
                new XElement("ContentValue", emp.FactValue)));



var result = new XElement(
    "DataDictionary",
    new[]
        {
            new XElement("filingInfo", fillingIngo), 
            new XElement("TaggableContent", taggableContent)
        });

或者使用group by:

var xEle = new XElement("DataDictionary",
    from fd in factDetails
    group fd by fd.ElementPrefix.Contains("dei") into gr
    select new XElement(gr.Key ? "filingInfo" : "TaggableContent",
                from emp in gr
                select new XElement(p.GetParameterType(emp.ElementType,emp.ElementPrefix),
                    new XElement("xbrlElementInfo",
                        new XAttribute("name", emp.ElementName),
                        new XElement("ContentValue", emp.FactValue)))));