使用XDocument读取XML值的困难

时间:2013-06-05 11:13:25

标签: c# linq-to-xml

我有一个xml文件,如

<ScriptFileNames>
  <SqlEye>
    <ScriptFile Name='_ws_CommandHistory_AllHistory.sql' Type='SP' SqlEyeAnalysisTime='00:00:01.7817594' FxCopAnalysisTime='00:00:00.2253670' FxCopWarningCount='0' SqlEyeWarningCount='2'>
          <SqlEyeWarnings>
            <SqlEyeWarning message='SD004: Check for existence object then Drop statement before create statement' />
            <SqlEyeWarning message='SP001: Set NoCount statement missing or it should be ON.' />
          </SqlEyeWarnings>
        </ScriptFile>
  </SqlEye>
</ScriptFileNames>

我希望输出为

FileName WarningMessage格式

e.g。

_ws_CommandHistory_AllHistory.sql   SD004: Check for existence object then Drop statement before create statement
_ws_CommandHistory_AllHistory.sql   SP001: Set NoCount statement missing or it should be ON.

我的尝试

string input = @"<ScriptFileNames>
  <SqlEye>
    <ScriptFile Name='_ws_CommandHistory_AllHistory.sql' Type='SP' SqlEyeAnalysisTime='00:00:01.7817594' FxCopAnalysisTime='00:00:00.2253670' FxCopWarningCount='0' SqlEyeWarningCount='2'>
          <SqlEyeWarnings>
            <SqlEyeWarning message='SD004: Check for existence object then Drop statement before create statement' />
            <SqlEyeWarning message='SP001: Set NoCount statement missing or it should be ON.' />
          </SqlEyeWarnings>
        </ScriptFile>
  </SqlEye>
</ScriptFileNames>";
XDocument doc = XDocument.Parse(input);
            XElement scriptFileNames = doc.Element("ScriptFileNames");

            var xx = (from x1 in scriptFileNames.Element("SqlEye").Elements("ScriptFile")
                      select new
                          {
                              Name = x1.Attribute("Name").Value                              
                          }).ToList();

我还有更多部分

<SqlEyeRemarks>
        <SqlEyeRemark message='SD001: Set QuotedIdentifier ON statement is missing or order mismatch or it should be ON.' />
        <SqlEyeRemark message='SD002: Set AnsiiNullsOn ON statement is missing or order mismatch or it should be ON.' />
        <SqlEyeRemark message='SD009: Missing or order mismatch of Grant statement.' />
      </SqlEyeRemarks>

我怎样才能得到它们?

2 个答案:

答案 0 :(得分:1)

您当前的代码仅迭代到ScriptFile级别。我怀疑最简单的方法是:

var warnings = doc.Descendants("SqlEyeWarning")
                  .Select(x => new {
                      FileName = (string) x.Parent.Parent.Attribute("Name"),
                      Message = (string) x.Attribute("message")
                  })
                  .ToList();

这使用x.Parent.ParentSqlEyeWarning元素过去SqlEyeWarningsScriptFile

我假设这里的所有 SqlEyeWarning元素都属于同一种结构。如果是,上面是最简单的。否则,您可以使用:

var warnings = doc.Root
                  .Element("SqlEye")
                  .Elements("ScriptFile")
                  .Elements("SqlEyeWarnings")
                  .Elements("SqlEyeWarning")
                  .Select(x => new {
                      FileName = (string) x.Parent.Parent.Attribute("Name"),
                      Message = (string) x.Attribute("message")
                  })
                  .ToList();

答案 1 :(得分:0)

请参阅下面的代码,该代码将向控制台写入文件名和相关的警告消息。

这种方法会将您的XML反序列化为可以使用的.NET对象。

小提示 - 尽量避免在XML中使用太多属性。考虑将ScriptFile属性转换为元素以提高可读性=](如果您选择使用它,则需要修改代码以反映更改 - 将XmlAttribute属性更改为XmlElement)。

祝你好运!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace ConsoleApplication1
{
    public class Program
    {
        static void Main(string[] args)
        {
            string input = @"<ScriptFileNames>
                              <SqlEye>
                                <ScriptFile Name='_ws_CommandHistory_AllHistory.sql' Type='SP' SqlEyeAnalysisTime='00:00:01.7817594' FxCopAnalysisTime='00:00:00.2253670' FxCopWarningCount='0' SqlEyeWarningCount='2'>
                                      <SqlEyeWarnings>
                                        <SqlEyeWarning message='SD004: Check for existence object then Drop statement before create statement' />
                                        <SqlEyeWarning message='SP001: Set NoCount statement missing or it should be ON.' />
                                      </SqlEyeWarnings>
                                    </ScriptFile>
                              </SqlEye>
                            </ScriptFileNames>";

            XDocument doc = XDocument.Parse(input);
            XmlSerializer serialiser = new XmlSerializer(typeof(ScriptFileNames));
            ScriptFileNames scriptNames = (ScriptFileNames)serialiser.Deserialize(doc.CreateReader());

            foreach (SqlEyeWarning warning in scriptNames.SqlEye.ScriptFile.SqlEyeWarnings)
            {
                Console.WriteLine(scriptNames.SqlEye.ScriptFile.Name + "\t" + warning.Message);
            }

            Console.ReadLine();
        }

        [XmlRoot]
        public class ScriptFileNames
        {
            [XmlElement("SqlEye")]
            public SqlEye SqlEye { get; set; }
        }

        public class SqlEye
        {
            [XmlElement("ScriptFile")]
            public ScriptFile ScriptFile { get; set; }
        }

        public class ScriptFile
        {
            [XmlArray("SqlEyeWarnings")]
            [XmlArrayItem("SqlEyeWarning", typeof(SqlEyeWarning))]
            public SqlEyeWarning[] SqlEyeWarnings { get; set; }

            [XmlAttribute("Name")]
            public string Name { get; set; }

            [XmlAttribute("Type")]
            public string Type { get; set; }

            [XmlAttribute("SqlEyeAnalysisTime")]
            public string SqlEyeAnalysisTime { get; set; }

            [XmlAttribute("FxCopAnalysisTime")]
            public string FxCopAnalysisTime { get; set; }

            [XmlAttribute("FxCopWarningCount")]
            public string FxCopWarningCount { get; set; }

            [XmlAttribute("SqlEyeWarningCount")]
            public string SqlEyeWarningCount { get; set; }
        }

        public class SqlEyeWarning
        {
            [XmlAttribute("message")]
            public string Message { get; set; }
        }
    }
}