1

I'm trying the parse the xml file at this link: http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.quakeml.

The problem I am having is that the foreach loop itself is not executing. I think its a problem with namespaces in the xml document.

Below is my code:

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();
    }
}`
2
  • What type of error do you get Commented May 8, 2015 at 20:34
  • well you need to add you namespace to your query Commented May 8, 2015 at 20:39

5 Answers 5

2

You have filled the NamespaceManager but you're not using any.
A quick glance suggests you should at least indicate that the root is in q:. Roughly, not tested:

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

PS: Working with namespaces and XML in general is a lot easier with the XElement class. It's worth investigating.

Sign up to request clarification or add additional context in comments.

Comments

2

Change this:

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

To this:

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

And your query should be changed to the following:

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

Why do you need this change? For the answer on this question take a look on a nice explanation here. But as others said, you'll be better to work with XDocument, it is newer and easier.

EDIT Modified queries in a loop:

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;

5 Comments

Ok this works fine. The foreach loop is executing :) but what about the nodes that are being selected in the loop?
you should do the same thing: write correct prefixes in the query and add namespace manager to the method call, for example node.SelectSingleNode("./def:origin/def:latitude/def:value", nmspc)
string location = (node.SelectSingleNode("./def:description/def:text", nmspc) != null) ? node.SelectSingleNode("./def:description/def:text", nmspc).InnerText.ToString() : string.Empty;
i did the above but its still not inserting the data into the database?
are you sure you didn't make a typo in queries? for example in this string string magnitudeType = (node.SelectSingleNode("magnitude/type/") != null) ? node.SelectSingleNode("magnitude/type/").InnerText.ToString() : string.Empty; you have extra slash at the end
1

I prefered to work with XElement/XDoc rather than XMLElement & Co because this it easier.

Basically, your query returns 0 elements, because you don't use the name space.

So foreach has no collection to parse.

You can do something like

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

// i.e. get all nodes with event (w/o respect of ns) var result = doc.Descendants ().Where ( s => s.Name.LocalName == "event"); foreach ( var item in result ) { Debug.WriteLine ( item.Value ); }

or with namespace

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

HTH

Comments

1

I suggest you work with linq to xml it's much easier :

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

1 Comment

As said by you, i tried this: XmlNodeList dataNodes = xmlDoc.SelectNodes("/q:quakeml/eventParameters/event", nmspc); but still the foreach is not executed...
0

This is much easier if you can use LinqToXml and 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;

}

1 Comment

This is awesome man :) It works like a charm (Y). But still i want to know the other way i was trying before why fails. But i'll use this technique also.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.