问题
I have an xml file as under
<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>
I want the output to be
FileName WarningMessage
format
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.
My attempt
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();
I also have I more section
<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>
How can I get them along?
回答1:
Your current code is only iterating to the ScriptFile
level. I suspect the simplest approach would be:
var warnings = doc.Descendants("SqlEyeWarning")
.Select(x => new {
FileName = (string) x.Parent.Parent.Attribute("Name"),
Message = (string) x.Attribute("message")
})
.ToList();
This uses x.Parent.Parent
to go up from the SqlEyeWarning
element past SqlEyeWarnings
to ScriptFile
.
I'm assuming that all SqlEyeWarning
elements here are within the same sort of structure. If they are, the above is simplest. Otherwise, you could use:
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();
回答2:
Please see the code below that will write to the console the file name and associated warning message.
This approach will deserialise your XML into .NET objects that are ready to use.
A small tip - try to avoid using too many attributes in your XML. Consider converting the ScriptFile attributes to elements to increase readability =] (You will need to modify the code to reflect the change if you choose to make it - change the XmlAttribute attributes to XmlElement).
Good luck!
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; }
}
}
}
来源:https://stackoverflow.com/questions/16938434/difficulty-in-reading-xml-values-using-xdocument