c# - 如何从具有一些嵌入数据的 XML 文档填充 C# 类?

标签 c# asp.net xml

我有一个 API 返回了这个:

http://services.aonaware.com/DictService/DictService.asmx?op=DefineInDict

<?xml version="1.0" encoding="utf-8"?>
<WordDefinition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://services.aonaware.com/webservices/">
  <Word>abandon</Word>
  <Definitions>
    <Definition>
      <Word>abandon</Word>
      <Dictionary>
        <Id>wn</Id>
        <Name>WordNet (r) 2.0</Name>
      </Dictionary>
      <WordDefinition>abandon
     n 1: the trait of lacking restraint or control; freedom from
          inhibition or worry; "she danced with abandon" [syn: {wantonness},
           {unconstraint}]
     2: a feeling of extreme emotional intensity; "the wildness of
        his anger" [syn: {wildness}]
     v 1: forsake, leave behind; "We abandoned the old car in the
          empty parking lot"
     2: stop maintaining or insisting on; of ideas, claims, etc.;
        "He abandoned the thought of asking for her hand in
        marriage"; "Both sides have to give up some calims in
        these negociations" [syn: {give up}]
     3: give up with the intent of never claiming again; "Abandon
        your life to God"; "She gave up her children to her
        ex-husband when she moved to Tahiti"; "We gave the
        drowning victim up for dead" [syn: {give up}]
     4: leave behind empty; move out of; "You must vacate your
        office by tonight" [syn: {vacate}, {empty}]
     5: leave someone who needs or counts on you; leave in the
        lurch; "The mother deserted her children" [syn: {forsake},
         {desolate}, {desert}]
</WordDefinition>
    </Definition>
  </Definitions>
</WordDefinition>

这是我用来检索 XML 数据的代码:

        WebRequest request = WebRequest.Create("http://services.aonaware.com/DictService/DictService.asmx/DefineInDict");
        request.Method = "POST";
        string postData = "dictId=wn&word=abandon";
        byte[] byteArray = Encoding.UTF8.GetBytes(postData);
        request.ContentType = "application/x-www-form-urlencoded";
        request.ContentLength = byteArray.Length;
        Stream dataStream = request.GetRequestStream();
        dataStream.Write(byteArray, 0, byteArray.Length);
        dataStream.Close();
        WebResponse response = request.GetResponse();
        Console.WriteLine(((HttpWebResponse)response).StatusDescription);
        dataStream = response.GetResponseStream();
        StreamReader reader = new StreamReader(dataStream);
        string responseFromServer = reader.ReadToEnd();
        Console.WriteLine(responseFromServer);
        reader.Close();
        dataStream.Close();
        response.Close();

我想将 XML 中的数据提取到定义类如下所示的列表中:

public class Def
{
    public string text { get; set; }
    public List<string> synonym { get; set; }
}

public class Definition
{
    public string type { get; set; } // single character: n or v or a 
    public List<Def> Def { get; set; }
}

有人可以给我一些建议,告诉我如何做到这一点,并展示我可以使用哪些选项来从 XML 中挑选类元素并将它们放入类中

因为我认为这个问题可能对许多其他人有帮助,所以我会开放一个大赏金,希望有人能花时间想出一个好的例子

更新:

对不起。我用 Synonym 弄错了。我现在改变了这个。希望它更有意义。同义词只是一个列表,我还用粗体显示了我需要的内容,因为到目前为止这两个答案似乎根本没有回答这个问题。谢谢。

最佳答案

我为单词定义创建了一个简单的解析器(很确定这里还有改进的余地):

解决方案1.0

class ParseyMcParseface
{
    /// <summary>
    /// Word definition lines
    /// </summary>
    private string[] _text;

    /// <summary>
    /// Constructor (Takes the innerText of the WordDefinition tag as input
    /// </summary>
    /// <param name="text">innerText of the WordDefinition</param>
    public ParseyMcParseface(string text)
    {
        _text = text.Split(new [] {'\n'}, StringSplitOptions.RemoveEmptyEntries)
            .Skip(1) // Skip the first line where the word is mentioned
            .ToArray();
    }

    /// <summary>
    /// Convert from single letter type to full human readable type
    /// </summary>
    /// <param name="c"></param>
    /// <returns></returns>
    private string CharToType(char c)
    {
        switch (c)
        {
            case 'a':
                return "Adjective";
            case 'n':
                return "Noun";
            case 'v':
                return "Verb";
            default:
                return "Unknown";
        }
    }

    /// <summary>
    /// Reorganize the data for easier parsing
    /// </summary>
    /// <param name="text">Lines of text</param>
    /// <returns></returns>
    private static List<List<string>> MakeLists(IEnumerable<string> text)
    {
        List<List<string>> types = new List<List<string>>();
        int i = -1;
        int j = 0;
        foreach (var line in text)
        {
            // New type (Noun, Verb, Adj.)
            if (Regex.IsMatch(line.Trim(), "^[avn]{1}\\ \\d+"))
            {
                types.Add(new List<string> { line.Trim() });
                i++;
                j = 0;
            }
            // New definition in the previous type
            else if (Regex.IsMatch(line.Trim(), "^\\d+"))
            {
                j++;
                types[i].Add(line.Trim());
            }
            // New line of the same definition
            else
            {
                types[i][j] = types[i][j] + " " + line.Trim();
            }
        }

        return types;
    }

    public List<Definition> Parse()
    {
        var definitionsLines = MakeLists(_text);

        List<Definition> definitions = new List<Definition>();

        foreach (var type in definitionsLines)
        {

            var defs = new List<Def>();
            foreach (var def in type)
            {
                var match = Regex.Match(def.Trim(), "(?:\\:\\ )(\\w|\\ |;|\"|,|\\.|-)*[\\[]{0,1}");
                MatchCollection syns = Regex.Matches(def.Trim(), "\\{(\\w|\\ )+\\}");

                List<string> synonymes = new List<string>();
                foreach (Match syn in syns)
                {
                    synonymes.Add(syn.Value.Trim('{', '}'));
                }

                defs.Add(new Def()
                {
                    text = match.Value.Trim(':', '[', ' '),
                    synonym = synonymes
                });
            }


            definitions.Add(new Definition
            {
                type = CharToType(type[0][0]),
                Def = defs
            });
        }
        return definitions;
    }
}

这是一个用法示例:

WebRequest request = 
WebRequest.Create("http://services.aonaware.com/DictService/DictService.asmx/DefineInDict");
request.Method = "POST";
string postData = "dictId=wn&word=abandon";
byte[] byteArray = Encoding.UTF8.GetBytes(postData);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = byteArray.Length;
Stream dataStream = request.GetRequestStream();
dataStream.Write(byteArray, 0, byteArray.Length);
dataStream.Close();
WebResponse response = request.GetResponse();
Console.WriteLine(((HttpWebResponse)response).StatusDescription);
dataStream = response.GetResponseStream();
StreamReader reader = new StreamReader(dataStream);
string responseFromServer = reader.ReadToEnd();


var doc = new XmlDocument();
doc.LoadXml(responseFromServer );
var el = doc.GetElementsByTagName("WordDefinition");

ParseyMcParseface parseyMcParseface = new ParseyMcParseface(el[1].InnerText);
var parsingResult = parseyMcParseface.Parse();
// parsingResult will contain a list of Definitions
// per the format specified in the question.

这是一个现场演示:https://dotnetfiddle.net/24IQ67

您还可以通过添加对该网络服务的引用来避免手动检索然后解析 XML。

解决方案2.0

我制作了一个小应用程序来执行此操作,然后解析定义。它托管here on GitHub (它太大了,无法在 StackOverflow 上发布):

public enum WordTypes
{
    Noun,
    Verb,
    Adjective,
    Adverb,
    Unknown
}

public class Definition
{
    public Definition()
    {
        Synonyms = new List<string>();
        Anotnyms = new List<string>();
    }
    public WordTypes WordType { get; set; }
    public string DefinitionText { get; set; }
    public List<string> Synonyms { get; set; }
    public List<string> Anotnyms { get; set; }

}

static class DefinitionParser
{
    public static List<Definition> Parse(string wordDefinition)
    {
        var wordDefinitionLines = wordDefinition.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries)
            .Skip(1)
            .Select(x => x.Trim())
            .ToList();

        var flatenedList = MakeLists(wordDefinitionLines).SelectMany(x => x).ToList();

        var result = new List<Definition>();
        foreach (var wd in flatenedList)
        {
            var foundMatch = Regex.Match(wd, @"^(?<matchType>adv|adj|v|n){0,1}\s*(\d*): (?<definition>[\w\s;""',\.\(\)\!\-]+)(?<extraInfoSyns>\[syn: ((?<wordSyn>\{[\w\s\-]+\})|(?:[,\ ]))*\]){0,1}\s*(?<extraInfoAnts>\[ant: ((?<wordAnt>\{[\w\s-]+\})|(?:[,\ ]))*\]){0,1}");

            var def = new Definition();

            if (foundMatch.Groups["matchType"].Success)
            {
                var matchType = foundMatch.Groups["matchType"];
                def.WordType = DefinitionTypeToEnum(matchType.Value);
            }

            if (foundMatch.Groups["definition"].Success)
            {
                var definition = foundMatch.Groups["definition"];
                def.DefinitionText = definition.Value;
            }

            if (foundMatch.Groups["extraInfoSyns"].Success && foundMatch.Groups["wordSyn"].Success)
            {
                foreach (Capture capture in foundMatch.Groups["wordSyn"].Captures)
                {
                    def.Synonyms.Add(capture.Value.Trim('{','}'));
                }
            }

            if (foundMatch.Groups["extraInfoAnts"].Success && foundMatch.Groups["wordAnt"].Success)
            {
                foreach (Capture capture in foundMatch.Groups["wordAnt"].Captures)
                {
                    def.Anotnyms.Add(capture.Value.Trim('{', '}'));
                }
            }

            result.Add(def);
        }
        return result;
    }

    private static List<List<string>> MakeLists(IEnumerable<string> text)
    {
        List<List<string>> types = new List<List<string>>();
        int i = -1;
        int j = 0;
        foreach (var line in text)
        {
            // New type (Noun, Verb, Adj.)
            if (Regex.IsMatch(line, "^(adj|v|n|adv){1}\\s\\d*"))
            {
                types.Add(new List<string> { line });
                i++;
                j = 0;
            }
            // New definition in the previous type
            else if (Regex.IsMatch(line, "^\\d+"))
            {
                j++;
                types[i].Add(line);
            }
            // New line of the same definition
            else
            {
                types[i][j] = types[i][j] + " " + line;
            }
        }

        return types;
    }

    private static WordTypes DefinitionTypeToEnum(string input)
    {
        switch (input)
        {
            case "adj":
                return WordTypes.Adjective;
            case "adv":
                return WordTypes.Adverb;
            case "n":
                return WordTypes.Noun;
            case "v":
                return WordTypes.Verb;
            default:
                return WordTypes.Unknown;
        }
    }
}

enter image description here

注意事项:

  • 这应该按预期工作
  • 解析自由文本不可靠
  • 您应该导入服务引用(如其他答案中所述),而不是手动解析 XML。

关于c# - 如何从具有一些嵌入数据的 XML 文档填充 C# 类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36714360/

相关文章:

asp.net - 是 SQL 注入(inject)吗?

asp.net - 如何在 mvc3 中创建自定义过滤器工具栏 html 帮助器

c# - 使用 ASP.NET MVC 形式的数据生成 xml 文件

javascript - ASP.Net @Html.TextBox 日期选择器

c# - 使用 LINQ 获取 1-2-3 分数并将其绑定(bind)到 View

java - Spring Integration xsl-来自数据库的资源

xml - log4j.xml - 警告找不到记录器的附加程序

xml - XSL 递归排序

c# - DLL 版本不匹配 : The located assembly's manifest definition does not match the assembly reference

c# - 检查边缘列表中子集的合理快速方法