Tricky Linq转换为XML

时间:2012-05-31 16:16:00

标签: xml linq

请查看下面的代码并建议需要做些什么才能获得输出中的额外最后一行,如预期输出所示

class test {

   static void Main(string[] args)
    {

        XDocument doc = XDocument.Load("E:\\BI_analytics\\Data\\so.xml");
        var query = from test in doc.Descendants("tester")
                    from testreq in test.Descendants("testRequest")
                    from testresp in test.Descendants("testResponse")
                    let id = testreq.Element("id") == null ? string.Empty : testreq.Element("id").Value

                  //  select id;
                    from itm in testresp.Descendants("item")
                    select new
                    {
                        ID = (string)id,
                        Name = (string)itm.Attribute("itemname"),
                        Code = (string)itm.Attribute("itemocde"),
                    };


        foreach (var result in query)
        {
            Console.WriteLine(result);
        }
    }
}

当前输出

{ ID = 2, Name = test item1, Code = 111 }
{ ID = 2, Name = test item2, Code = 222 }
{ ID = 3, Name = test item3, Code = 333 }
{ ID = 3, Name = test item4, Code = 444 }

预期输出

{ ID = 2, Name = test item1, Code = 111 }
{ ID = 2, Name = test item2, Code = 222 }
{ ID = 3, Name = test item3, Code = 333 }
{ ID = 3, Name = test item4, Code = 444 }
{ ID = 4, Name = , Code = }
<?xml version="1.0" encoding="utf-8"?>
<root>
  <tester>
    <testRequest>
      <id>2</id>
    </testRequest>
    <testResponse>
      <items>
        <item itemname="test item1" itemocde="111"/>
        <item itemname="test item2" itemocde="222"/>
      </items>
    </testResponse>
  </tester>
  <tester>
    <testRequest>
      <id>3</id>
    </testRequest>
    <testResponse>
      <items>
        <item itemname="test item3" itemocde="333"/>
        <item itemname="test item4" itemocde="444"/>
      </items>
    </testResponse>
  </tester>
  <tester>
    <testRequest>
      <id>4</id>
    </testRequest>
    <testResponse>
      <items />
    </testResponse>
  </tester>
</root>

2 个答案:

答案 0 :(得分:3)

我使用一个类来帮助我返回值,即使它是null,如下所示:

public static class LinqToXMLUtility
{
    /// <summary>
    /// Used to Get check the XElement Value and return 
    /// empty string if it is null (used for optional or missing xml items)
    /// </summary>
    /// <param name="pElement"></param>
    /// <param name="pstrElementName"></param>
    /// <returns></returns>
    public static string GetXElementValue(XElement pElement, string pstrElementName)
    {
        string strRet = string.Empty;
        try
        {
            XElement lElement = pElement.Element(pstrElementName);
            if (lElement != null)
            {
                strRet = lElement.Value;
            }
        }
        catch { }
        return strRet;
    }
}

并像这样使用它。

class test
{
    static void Main(string[] args)
    {
        XDocument doc = XDocument.Load("E:\\BI_analytics\\Data\\so.xml");
        var query = from test in doc.Descendants("tester")
                    from testreq in test.Descendants("testRequest")
                    from testresp in test.Descendants("testResponse")
                    let id = testreq.Element("id") == null ? string.Empty : 
                             testreq.Element("id").Value

                    //  select id;
                    from itm in testresp.Descendants("item")
                    select new
                    {
                        ID = LinqToXMLUtility.GetXElementValue(itm, "id"),
                        Name = LinqToXMLUtility.GetXElementValue(itm, "itemname"),
                        Code =  LinqToXMLUtility.GetXElementValue(itm, "itemocde"),
                    };


        foreach (var result in query)
        {
            Console.WriteLine(result);
        }
    }
}

答案 1 :(得分:2)

这是问题所在:

from itm in testresp.Descendants("item")

你没有拥有任何item元素,所以你可能想要:

from itm in testresp.Descendants("item").DefaultIfEmpty()

......此时你需要:

select new
{
    ID = (string)id,
    Name = itm == null ? "" : (string)itm.Attribute("itemname"),
    Code = itm == null ? "" : (string)itm.Attribute("itemocde"),
};