2011-04-16 85 views
0

我在解析下面的soap响应时遇到了问题。这是我第一次使用LINQ,并且必须使用XML而不是SOAP信封。我如何获取不同“项目”的值。我知道有不同的选项(使用添加服务引用),但它不是我当前项目中的一个选项。用LINQ解析肥皂响应

<SOAP-ENV:Envelope 
xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" 
xmlns:ns1=\"http://random.com/api/1/service\" 
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" 
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" 
xmlns:ns2=\"http://xml.apache.org/xml-soap\" 
xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" 
SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"> 
    <SOAP-ENV:Body> 
     <ns1:getBeatlesResponse> 
      <return xsi:type=\"ns2:Map\"> 
       <item> 
        <key xsi:type=\"xsd:string\">error</key> 
        <value xsi:type=\"xsd:string\">OK</value> 
       </item> 
       <item> 
        <key xsi:type=\"xsd:string\">Beatles</key> 
        <value xsi:type=\"ns2:Map\"> 
         <item> 
          <key xsi:type=\"xsd:int\">9</key> 
          <value xsi:type=\"xsd:string\">John Lennon</value> 
         </item> 
         <item> 
          <key xsi:type=\"xsd:int\">12</key> 
          <value xsi:type=\"xsd:string\">Paul McCartney</value> 
         </item> 
         <item> 
          <key xsi:type=\"xsd:int\">25</key> 
          <value xsi:type=\"xsd:string\">George Harrison</value> 
         </item> 
         <item> 
          <key xsi:type=\"xsd:int\">184</key> 
          <value xsi:type=\"xsd:string\">Ringo Starr</value> 
         </item> 
        </value> 
       </item> 
      </return> 
     </ns1:getBeatlesResponse> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

在此先感谢

回答

2

这是一个相当棘手,因为你必须有这或许可以有太多的项目项目的项目......所以如果你做这样的事情

var returnResult = (from r in document.Descendants("item") 
          select r).ToList(); 

,你会得到所有的物品分开,一个具有在一个所有的值...

编辑:

这工作有点细

XDocument document = XDocument.Load(@"XMLFile1.xml"); 

     List<Item> items = new List<Item>(); 

     var returnResult = (from r in document.Descendants("item") 
          select r).ToList(); 

     foreach (XElement xElement in returnResult) 
     { 

      Item item = new Item(); 

      item.Key = xElement.Element("key") != null ? xElement.Element("key").Value : ""; 
      item.Value = xElement.Element("value") != null ? xElement.Element("value").Value : ""; 

      items.Add(item); 
     } 

     //sort the list to get the one that have the rest to the end 
     var sorted = (from s in items 
         orderby s.Value.Length ascending 
         select s).ToList(); 

     List<Item> finalList = new List<Item>(); 

     items.Clear(); 
     for (int i = 0; i < sorted.Count - 1; i++) 
     { 
      for (int j = 1; j < sorted.Count; j++) 
      { 
       if (sorted[j].Value.Contains(sorted[i].Value) && 
        sorted[j].Value.Length > sorted[i].Value.Length) 
       { 
        Item itm = new Item(); 
        itm.Key = sorted[j].Key; 
        KeyValuePair<string, string> kvp = new KeyValuePair<string, string>(sorted[i].Key,sorted[i].Value); 
        itm.Items.Add(kvp); 
        items.Add(itm); 

       } 
       else 
       { 
        if (!finalList.Contains(sorted[i])) 
         finalList.Add(sorted[i]); 
       } 
      } 
     } 
class Item 
{ 
    public List<Item> Items { get; set; } 
    public string Key { get; set; } 
    public string Value {get;set;} 
    public Item() 
    { 
     Items = new List<Item>(); 
    } 
} 

您现在可以看到所有子项都有正确的键......只有ok/error会产生一些麻烦......但是您可以从最终列表中获取它们,并在它们不是键值的情况下选择它们对...

希望这有助于

+0

非常感谢!这样做的工作,但我觉得很奇怪多少复杂性带来了其他属性里面的同名其属性时......我想真正的解决方案将改变属性名称,但我不参与开发的Web服务 – retain 2011-04-17 01:19:24

+0

问题是,如果它会像 ...那么它可能会更好...那么它会很容易...因为每个你确切知道哪些子元素属于它,你不必作弊:) – 2011-04-17 05:39:50

0

您应该能够通过加载到一个XDocument解析这个。然后,您可以通过指定元素名称来选择所需的值。最后,您可以将这些值作为新的匿名类型返回。一个例子可以在对这个问题的回答中找到:Using LINQ to XML to Parse a SOAP message

让我知道如果你有任何问题。