使用命名空间解析XML文件

时间:2015-05-08 20:24:19

标签: c# xml

我尝试通过此链接解析xml文件:http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.quakeml

我遇到的问题是foreach循环本身没有执行。我认为这是xml文档中名称空间的问题。

以下是我的代码:

protected void btnStoreXMLData_Click(object sender, EventArgs e)
{
    SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["EarthquakeCS"].ConnectionString);
    SqlCommand cmd = new SqlCommand();
    try
    {
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(Server.MapPath("~/App_Data/all_hour.xml"));

        XmlNamespaceManager nmspc = new XmlNamespaceManager(xmlDoc.NameTable);
        nmspc.AddNamespace("", "http://quakeml.org/xmlns/bed/1.2");
        nmspc.AddNamespace("catalog", "http://anss.org/xmlns/catalog/0.1");
        nmspc.AddNamespace("q", "http://quakeml.org/xmlns/quakeml/1.2");

        XmlNodeList dataNodes = xmlDoc.SelectNodes("/quakeml/eventParameters/event", nmspc);

        //ScriptManager.RegisterStartupScript(this, this.GetType(), "Message", "alert('test0');", true);

        foreach (XmlNode node in dataNodes)
        {
            ScriptManager.RegisterStartupScript(this, this.GetType(), "Message", "alert('test1');", true);

            string location = (node.SelectSingleNode("description/text") != null) ? node.SelectSingleNode("description/text").InnerText.ToString() : string.Empty;
            string time = (node.SelectSingleNode("origin/time/value") != null) ? node.SelectSingleNode("origin/time/value").InnerText.ToString() : string.Empty;
            string longitude = (node.SelectSingleNode("origin/longitude/value") != null) ? node.SelectSingleNode("origin/longitude/value").InnerText.ToString() : string.Empty;
            string latitude = (node.SelectSingleNode("origin/latitude/value") != null) ? node.SelectSingleNode("origin/latitude/value").InnerText.ToString() : string.Empty;
            string depth = (node.SelectSingleNode("origin/depth/value") != null) ? node.SelectSingleNode("origin/depth/value").InnerText.ToString() : string.Empty;
            string magnitude = (node.SelectSingleNode("magnitude/mag/value") != null) ? node.SelectSingleNode("magnitude/mag/value").InnerText.ToString() : string.Empty;
            string magnitudeType = (node.SelectSingleNode("magnitude/type/") != null) ? node.SelectSingleNode("magnitude/type/").InnerText.ToString() : string.Empty;

            cmd.CommandText = "INSERT INTO tblEarthquake (Location,Time,Latitude,Longitude,Depth,Magnitude,MagnitudeType) "
                            + "VALUES (@Location,@Time,@Latitude,@Longitude,@Depth,@Magnitude,@MagnitudeType)";
            cmd.CommandType = CommandType.Text;

            cmd.Parameters.Clear();
            cmd.Parameters.AddWithValue("@Location", location);
            cmd.Parameters.AddWithValue("@Time", time);
            cmd.Parameters.AddWithValue("@Latitude", latitude);
            cmd.Parameters.AddWithValue("@Longitude", longitude);
            cmd.Parameters.AddWithValue("@Depth", depth);
            cmd.Parameters.AddWithValue("@Magnitude", magnitude);
            cmd.Parameters.AddWithValue("@MagnitudeType", magnitudeType);

            cmd.Connection = con;

            if (con.State == ConnectionState.Closed)
            {
                con.Open();
            }

            int result = cmd.ExecuteNonQuery();

            if (result > 0)
            {
                //XML data has been inserted
            }
            else
            {
                //XML data has not been inserted
            }
        }

    }
    catch (Exception ex)
    {
        ScriptManager.RegisterStartupScript(this, this.GetType(), "Message", "alert('Error occured : " + ex.Message.ToString() + "');", true);
        return;
    }
    finally
    {
        con.Close();
        cmd.Dispose();
    }
}`

5 个答案:

答案 0 :(得分:2)

您已经填充了NamespaceManager,但您没有使用任何 快速浏览一下,建议您至少应指出根位于q:。粗略地,未经测试:

// ... xmlDoc.SelectNodes("/quakeml/eventParameters/event", nmspc);
   ... xmlDoc.SelectNodes("/q:quakeml/eventParameters/event", nmspc);

PS:使用XElement类,使用命名空间和XML通常会容易得多。值得研究。

答案 1 :(得分:2)

改变这个:

nmspc.AddNamespace("", "http://quakeml.org/xmlns/bed/1.2");

对此:

nmspc.AddNamespace("def", "http://quakeml.org/xmlns/bed/1.2");

您的查询应更改为以下内容:

/q:quakeml/def:eventParameters/def:event

为什么需要这个改变?关于这个问题的答案,请看一个很好的解释here。但正如其他人所说,与XDocument合作更好,它更新更容易。

编辑循环中修改后的查询:

string location = (node.SelectSingleNode("./def:description/def:text", nmspc) != null) ? node.SelectSingleNode("./def:description/def:text", nmspc).InnerText.ToString() : string.Empty;
string time = (node.SelectSingleNode("./def:origin/def:time/def:value", nmspc) != null) ? node.SelectSingleNode("./def:origin/def:time/def:value", nmspc).InnerText.ToString() : string.Empty;
string longitude = (node.SelectSingleNode("./def:origin/def:longitude/def:value", nmspc) != null) ? node.SelectSingleNode("./def:origin/def:longitude/def:value", nmspc).InnerText.ToString() : string.Empty;
string latitude = (node.SelectSingleNode("./def:origin/def:latitude/def:value", nmspc) != null) ? node.SelectSingleNode("./def:origin/def:latitude/def:value", nmspc).InnerText.ToString() : string.Empty;
string depth = (node.SelectSingleNode("./def:origin/depth/def:value", nmspc) != null) ? node.SelectSingleNode("./def:origin/def:depth/def:value", nmspc).InnerText.ToString() : string.Empty;
string magnitude = (node.SelectSingleNode("./def:magnitude/def:mag/def:value", nmspc) != null) ? node.SelectSingleNode("./def:magnitude/def:mag/def:value", nmspc).InnerText.ToString() : string.Empty;
string magnitudeType = (node.SelectSingleNode("./def:magnitude/def:type", nmspc) != null) ? node.SelectSingleNode("./def:magnitude/def:type", nmspc).InnerText.ToString() : string.Empty;

答案 2 :(得分:0)

我建议你使用linq到xml它更容易:

XElement xmlDoc = XElement.Load(Server.MapPath("~/App_Data/all_hour.xml"));
var dataNodes = xmlDoc.Descendants().Where(s => s.Name.LocalName == "event"); 

答案 3 :(得分:0)

我更喜欢使用XElement / XDoc而不是XMLElement& Co因为这更容易。

基本上,您的查询返回0个元素,因为您不使用名称空间。

所以foreach没有要解析的集合。

您可以执行类似

的操作
using System.Xml.Linq; //to use XElement XDoc etc

XDocument xDoc = new XDocument ();
XDocument doc = XDocument.Parse ( xmlIn );  -> xmlIn contains your XML code to parse as string

//即获取所有带有事件的节点(不考虑ns)     var result = doc.Descendants()。Where(s => s.Name.LocalName ==" event");     foreach(结果中的var项)     {         Debug.WriteLine(item.Value);     }

或使用命名空间

var result = doc.Descendants ().Where ( s => s.Name.LocalName == "event" 
&& 
s.Name.NameSpaceName == "myNamespace");

HTH

答案 4 :(得分:0)

如果您可以使用LinqToXml和XDocument,这会容易得多。

var document = XDocument.Load("http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.quakeml");
XNamespace rNs = "http://quakeml.org/xmlns/bed/1.2";

var events = document.Root.Descendants(rNs + "eventParameters").Elements(rNs + "event");
foreach (var ev in events)
{
    var location = ev.Descendants(rNs + "description").Descendants(rNs + "text").Single().Value;

    var originElement = ev.Descendants(rNs + "origin");
    var time = originElement.Descendants(rNs + "time").Descendants(rNs + "value").Single().Value;
    var longitude = originElement.Descendants(rNs + "longitude").Descendants(rNs + "value").Single().Value;
    var latitude = originElement.Descendants(rNs + "latitude").Descendants(rNs + "value").Single().Value;
    var depth = originElement.Descendants(rNs + "depth").Descendants(rNs + "value").Single().Value;

    var magnitudeElement = ev.Descendants(rNs + "magnitude");
    var magnitude = magnitudeElement.Descendants(rNs + "mag").Descendants(rNs + "value").Single().Value;
    var magnitudeType = magnitudeElement.Descendants(rNs + "type").Single().Value;

}