【问题标题】:looking for a better way of parsing XML retrieved from web API c#寻找一种更好的方法来解析从 web API c# 检索的 XML
【发布时间】:2019-01-06 17:41:05
【问题描述】:

我整天都在尝试解析从 Web api 检索到的 XML。这是我发现的唯一对我有用的实现。我尝试了 Serializer 类,但似乎无法让它工作。

我需要从中获取数据以拥有许多元素的一些 Web API,而这种实现似乎不是非常具有可扩展性...

我对此比较陌生,因此不胜感激。理想的情况是,如果有人可以向我展示如何使用更少的代码来获得与所示相同的功能。我想使用序列化程序类。

List<OpeningHours> openingHoursList = new List<OpeningHours>();
HttpClient client = new HttpClient();
Uri geturi = new Uri("Insert Uri name");

HttpResponseMessage responseGet = await client.GetAsync(geturi);         
string response = await responseGet.Content.ReadAsStringAsync();
XDocument doc = XDocument.Parse(response);

foreach (var item in doc.Descendants("OpenHours"))
{
    openingHoursList.Add(new OpeningHours() { 
        DayOfWeek = item.Element("DayOfWeek").Value.ToString(),
        CloseTime = item.Element("CloseTime").Value.ToString(),
        OpenTime = item.Element("OpenTime").Value.ToString()
    });
}

作为参考,这是我目前正在尝试解析的 XML。

<NewDataSet>
<OpenHours>
<DayOfWeek>Wednesday </DayOfWeek>
<OpenTime>07:30:00</OpenTime>
<CloseTime>18:00:00</CloseTime>
</OpenHours>
<OpenHours>
<DayOfWeek>Thursday </DayOfWeek>
<OpenTime>07:30:00</OpenTime>
<CloseTime>18:00:00</CloseTime>
</OpenHours>
<OpenHours>
<DayOfWeek>Monday </DayOfWeek>
<OpenTime>07:30:00</OpenTime>
<CloseTime>18:00:00</CloseTime>
</OpenHours>
<OpenHours>
<DayOfWeek>Tuesday </DayOfWeek>
<OpenTime>07:30:00</OpenTime>
<CloseTime>18:00:00</CloseTime>
</OpenHours>
<OpenHours>
<DayOfWeek>Friday </DayOfWeek>
<OpenTime>07:30:00</OpenTime>
<CloseTime>18:00:00</CloseTime>
</OpenHours>
</NewDataSet>

但是,我想解析这样的东西......

这就是我所说的可扩展的意思。如果我使用我当前的解决方案,我需要手动初始化我的 C# 类的每个字段。除此之外,一些 XML 元素有不同数量的死者......

<Dish>
<DishID>180</DishID>
<DishName>Caesar Salad (v) - Large</DishName>
<DishDesc>
Romaine Lettuce, Homemade Croutons, Shaved Grana Padano, Black Pepper & Caesar Dressing (separate) (v)
</DishDesc>
<DishPrice>21.5000</DishPrice>
<DishCat>22</DishCat>
<DishPosition>6</DishPosition>
<DishSpecial>0</DishSpecial>
<DishOn>true</DishOn>
<DishNumber/>
<DishHasOptions>false</DishHasOptions>
<VATable>true</VATable>
<UPC/>
<SKU/>
<Timer>0</Timer>
<FilterClasses/>
<DishDesc2/>
</Dish>
<Dish>
<DishID>179</DishID>
<DishName>Caesar Salad (v) - Small.</DishName>
<DishDesc/>
<DishPrice>4.3000</DishPrice>
<DishCat>22</DishCat>
<DishPosition>7</DishPosition>
<DishSpecial>0</DishSpecial>
<DishOn>true</DishOn>
<DishNumber/>
<DishHasOptions>false</DishHasOptions>
<VATable>true</VATable>
<UPC/>
<SKU/>
<Timer>0</Timer>
<FilterClasses/>
<DishDesc2/>
</Dish>
<Dish>
<DishID>53</DishID>
<DishName>Caesar salad (v)(small or large)</DishName>
<DishDesc>
Romaine lettuce, parmesan shavings, croutons with Caesar dressing
</DishDesc>
<DishPrice>4.0000</DishPrice>
<DishCat>7</DishCat>
<DishPosition>4</DishPosition>
<DishSpecial>0</DishSpecial>
<DishOn>false</DishOn>
<DishNumber>0</DishNumber>
<DishHasOptions>true</DishHasOptions>
<VATable>true</VATable>
<UPC/>
<SKU/>
<Timer>0</Timer>
<FilterClasses/>
<DishDesc2/>
<Option>
<DishOptionID>62</DishOptionID>
<DishID>53</DishID>
<DishOptionDesc>Select your size</DishOptionDesc>
<DishOptionSeqNo>1</DishOptionSeqNo>
<DishOptionPickerType>3</DishOptionPickerType>
<SubOption>
<dishSubOptionID>955</dishSubOptionID>
<DishOptionID>62</DishOptionID>
<DishSubOptionDesc>Small</DishSubOptionDesc>
<DishSubOptionPrice>0.0000</DishSubOptionPrice>
<DefaultChoice>true</DefaultChoice>
<DishID>53</DishID>
<DishSubOptionSeqNo>0</DishSubOptionSeqNo>
</SubOption>
<SubOption>
<dishSubOptionID>956</dishSubOptionID>
<DishOptionID>62</DishOptionID>
<DishSubOptionDesc>Large</DishSubOptionDesc>
<DishSubOptionPrice>15.0000</DishSubOptionPrice>
<DefaultChoice>false</DefaultChoice>
<DishID>53</DishID>
<DishSubOptionSeqNo>0</DishSubOptionSeqNo>
</SubOption>
</Option>
</Dish>

【问题讨论】:

  • 因为你想知道你做错了什么。 #1:不要通过添加不是答案的答案来影响您的帖子。如果它没有引起足够的关注,请对其进行编辑,澄清并添加更多细节。如果它仍然没有引起足够的关注,考虑帮助其他人获得声望,你可以在这个问题上悬赏。 #2:不要编辑你的帖子来添加与问题无关的信息。 (您的最后一次编辑根本没有澄清您的问题)。我强烈建议您阅读Writing the perfect question
  • @FrankerZ 我已经编辑了我的问题,希望它现在更有意义。我一定会阅读您发送的链接。感谢您的反馈。

标签: c# .net xml parsing


【解决方案1】:

如果您只想要更短的代码,您可以在这里寻找 Linq Select 方法,例如:

using System.Linq;
using System.Xml.Linq;

...

List<OpeningHours> openingHoursList = doc.Descendants("OpenHours").Select(x => new OpeningHours()
{
    DayOfWeek = x.Element("DayOfWeek").Value.ToString(),
    CloseTime = x.Element("CloseTime").Value.ToString(),
    OpenTime = x.Element("OpenTime").Value.ToString()
}).ToList();

习惯 lambdas 并在同一语句中创建和分配变量将有助于您编写更短的代码,但最短的代码并不总是最佳选择,例如在可扩展性和可维护性也是优先考虑的情况下。

因为您没有提供太多要解析的 XML 示例,所以我可以安全地推荐更多内容 - 我还没有找到一种可以优雅地处理的单一、自我扩展的 XML 解析方法各种用途。 我过去使用的另一种方法是将焦点转移到数据类本身,在本例中为 OpeningHours。 在您的 OpeningHours 类中,创建一个接受 XElement 作为参数的构造函数,并在其中编写代码以验证和解析该 XML:

//in your OpeningHours class:
public OpeningHours(XElement xmlResponse)
{
    DayOfWeek = xmlResponse.Element("DayOfWeek").Value.ToString();
    CloseTime = xmlResponse.Element("CloseTime").Value.ToString();
    OpenTime = xmlResponse.Element("OpenTime").Value.ToString();
} //etc..

然后在您的解析方法中,将 .Select() 中的 lambda 替换为:

List<OpeningHours> openingHoursList = doc.Descendants("OpenHours")
     .Select(x => new OpeningHours(x)).ToList();

以这种方式构建您的类有助于将相关逻辑与其加载到的结构保持在一起,并且随着新属性的添加,我发现更新相关的 XML 解析例程更加容易。

【讨论】:

  • 我已经添加了对我试图解析的内容的引用......我相信你的回答仍然适用于你所说的。我只是想增加清晰度
  • 不幸的是,我的声望低于 15 并且还不能将任何答案标记为可接受...当我有一些声望时,我会确保将其标记为可接受的。感谢您的宝贵时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-13
  • 1970-01-01
  • 2014-10-21
  • 2019-07-27
  • 2018-06-25
相关资源
最近更新 更多