michael.davis Posted August 27, 2012 Share Posted August 27, 2012 Good Monday Everyone! I am working on some code to pull in an XML formatted page from the internet and break it out into variables. I am not sure what I am missing here, but it will not parse the data. I am sure something simple. Here is the web link: http://www.amecim.com/metronashvillewater/metronashvilleraingaugeservice.asmx/getAllGauges15m Listed below is the code: <?php // // 15 Minute Gauge Data // $xml = new SimpleXMLElement('http://www.amecim.com/metronashvillewater/metronashvilleraingaugeservice.asmx/getAllGauges15m', 0, true); foreach ($xml->clsRainGaugeReading as $row) { printf("Sample Date: %s\n", $row->SampleDate); echo "<br>"; printf("Sample Time: %s\n", $row->SampleTime); echo "<br>"; printf("Gauge Name: %u\n", $row->GaugeName); echo "<br>"; printf("Sample Value: %u\n", $row->SampleValue); echo "<br>"; echo "<br>"; } ?> Thanks in advance for any help. Mike Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/ Share on other sites More sharing options...
Drongo_III Posted August 27, 2012 Share Posted August 27, 2012 You might have more luck with SimpleXML_load_file to parse in xml from a url. http://php.net/manual/en/function.simplexml-load-file.php Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372912 Share on other sites More sharing options...
michael.davis Posted August 27, 2012 Author Share Posted August 27, 2012 Interesting. I used the SimpleXMLElement in a previous script and works fine. Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372918 Share on other sites More sharing options...
xyph Posted August 27, 2012 Share Posted August 27, 2012 Your method is fine, you've just mis-understood your structure. Use this to view your structure. <?php // // 15 Minute Gauge Data // $xml = new SimpleXMLElement('http://www.amecim.com/metronashvillewater/metronashvilleraingaugeservice.asmx/getAllGauges15m', 0, true); echo '<pre>'; print_r($xml); echp '</pre>' ?> Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372925 Share on other sites More sharing options...
Drongo_III Posted August 27, 2012 Share Posted August 27, 2012 Hey mate Sorry I only suggested that because it's generally what I use. This will work to get the child elements for each clsRainGaugeReading element. I am sure there are lots of cleaner ways to get them but it might put you on the right track <?php //$xml = new SimpleXML $xml = SimpleXML_load_file('http://www.amecim.com/metronashvillewater/metronashvilleraingaugeservice.asmx/getAllGauges15m', 'SimpleXMLIterator'); $firstChildrenArray = array(); // going to hold parent elements $secondChildArray = array(); // going to hold child elements of each clsRainGaugeReading foreach($xml->children() as $child) { $firstChildrenArray[] = $child->getName(); } foreach($firstChildrenArray as $v){ $secondChildArray[] =$xml->{$v}->clsRainGaugeReading->children(); } echo "<pre>"; print_r($firstChildrenArray); print_r($secondChildArray); ?> Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372931 Share on other sites More sharing options...
michael.davis Posted August 27, 2012 Author Share Posted August 27, 2012 So to break it out into two different arrays will work best? Make sense. Ok...brain dump here. I believe my brain is fried now. To list the matching first array item with the first array data fields, I need to add? Thanks for your help! Mike Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372934 Share on other sites More sharing options...
Drongo_III Posted August 27, 2012 Share Posted August 27, 2012 Well as i said, there may well be a better way to do it. Not quite sure I follow your question. What do yo want to do? So to break it out into two different arrays will work best? Make sense. Ok...brain dump here. I believe my brain is fried now. To list the matching first array item with the first array data fields, I need to add? Thanks for your help! Mike Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372940 Share on other sites More sharing options...
Drongo_III Posted August 27, 2012 Share Posted August 27, 2012 Oh wait I think i get you try this: <?php //$xml = new SimpleXML $xml = SimpleXML_load_file('http://www.amecim.com/metronashvillewater/metronashvilleraingaugeservice.asmx/getAllGauges15m', 'SimpleXMLIterator'); $firstChildrenArray = array(); // going to hold parent elements $secondChildArray = array(); // going to hold child elements of each clsRainGaugeReading foreach($xml->children() as $child) { $firstChildrenArray[] = $child->getName(); } foreach($firstChildrenArray as $v){ $secondChildArray[$v] =$xml->{$v}->clsRainGaugeReading->children(); } echo "<pre>"; print_r($firstChildrenArray); print_r($secondChildArray); That will give you an associative array that matches the parent element to the children. You might want some logic in the foreach to handle null values too. For instance, "Brentwood" has no child elements so throws a warning. So to break it out into two different arrays will work best? Make sense. Ok...brain dump here. I believe my brain is fried now. To list the matching first array item with the first array data fields, I need to add? Thanks for your help! Mike Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372944 Share on other sites More sharing options...
michael.davis Posted August 27, 2012 Author Share Posted August 27, 2012 Thanks for your help Drongo_III! What I am trying to do is pull in the data and format it in a line format to be ingested into our database. What I would like to do is put the site and related data into one line at a time. Fore example: SITE DATE TIME VALUE BntCrk : 82712 DH1640/0 Does that make sense? Thanks! Mike Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372946 Share on other sites More sharing options...
Drongo_III Posted August 27, 2012 Share Posted August 27, 2012 Hey mate If that's your purpose then I've tweaked the code slightly so you end up with a conventional array and not an array of xmlobjects (that in my my opinion are harder to access). <?php //$xml = new SimpleXML $xml = SimpleXML_load_file('http://www.amecim.com/metronashvillewater/metronashvilleraingaugeservice.asmx/getAllGauges15m'); $firstChildrenArray = array(); // going to hold parent elements $secondChildArray = array(); // going to hold child elements of each clsRainGaugeReading foreach($xml->children() as $child) { $firstChildrenArray[] = $child->getName(); } // cycle through parent elements array so we deal with each in turn foreach($firstChildrenArray as $v){ // now for every parent element get the object vars for each child element foreach($xml->{$v}->clsRainGaugeReading as $vv){ $secondChildArray[] = get_object_vars($vv); // add object var value to array } } echo "<pre>"; // get rid of this line print_r($secondChildArray); // just to demonstrate end result echo "" . $secondChildArray[3]['SampleDate'] ; ?> So as you can see in the very last echo line you can then access each entry as a multi-dimensional array, which you can then simply use in your insert statement for your database. Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372969 Share on other sites More sharing options...
michael.davis Posted August 27, 2012 Author Share Posted August 27, 2012 Hi Drongo_III! That is exactly what I needed. Thanks!!!! Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372974 Share on other sites More sharing options...
michael.davis Posted August 27, 2012 Author Share Posted August 27, 2012 http://www.amecim.com/metronashvillewater/metronashvilleraingaugeservice.asmx/getAllGaugesAllIntervals The file above has 15 min, 30 minute, 1 hour, 2 hour, 4 hour, 6 hour and 24 values in this file. The USGS prefers we source this to gather all intervals and data associated with that interval that we require. This is really nice as it will be a one sources, yet the php code that we are working on slightly changes. Could use some help. Thanks! Mike Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372978 Share on other sites More sharing options...
michael.davis Posted August 27, 2012 Author Share Posted August 27, 2012 Ok I just edited the code and can get the 24 hour data. <?php //$xml = new SimpleXML $xml = SimpleXML_load_file('http://www.amecim.com/metronashvillewater/metronashvilleraingaugeservice.asmx/getAllGaugesAllIntervals'); $firstChildrenArray = array(); // going to hold parent elements $secondChildArray = array(); // going to hold child elements of each clsRainGaugeReading foreach($xml->children() as $child) { $firstChildrenArray[] = $child->getName(); } foreach($firstChildrenArray as $v){ foreach($xml->{$v}->TwentyfourHour as $vv){ $secondChildArray[] = get_object_vars($vv); } } echo "<pre>"; // get rid of this line print_r($secondChildArray); // just to demonstrate end result echo "" . $secondChildArray[3]['GaugeName'] ; ?> Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1372986 Share on other sites More sharing options...
salathe Posted August 27, 2012 Share Posted August 27, 2012 There is absolutely no need to create that array of "first children" names, only to use it to get the readings that you want. There is also no need to loop over the readings once to get them into an array, then loop over them again in array form to do whatever you want with them. It's all looking like doing unnecessary work. $data_url = 'http://www.amecim.com/metronashvillewater/metronashvilleraingaugeservice.asmx/getAllGaugesAllIntervals'; $package = new SimpleXMLElement($data_url, NULL, TRUE); foreach($package->children() as $gauge) { $sample = $gauge->TwentyfourHour; // Access the data using the tag name // e.g. $sample->GaugeName } If you haven't already, have a good (re-)read through the SimpleXML Basic Usage manual page which has lots of examples and instructions. The key take-home point, I think, is that you need to remember how the SimpleXML object structure relates to the XML structure. For example, the first SimpleXMLElement object ($package) contains the <clsRainGaugeIntervalSetPackage> element. Then we loop over its children(), which are the <BntCrk>, <Brentwood>, <GibsonCrk> ... elements. For each of those children, we grab the <TwentyfourHour> element and then you are left to get the child elements for whichever bits of information you want (see the comment). Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373002 Share on other sites More sharing options...
Drongo_III Posted August 27, 2012 Share Posted August 27, 2012 Well that does look cleaner :/ I did say there was probably a better way... And if you didn't like my last offering then you'll positively hate what I did to get the results for each timeslot. I will go brush up on my simplexml i think... :-\ Yeah three levels of foreach was probably never going to be a winner... Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373009 Share on other sites More sharing options...
Drongo_III Posted August 27, 2012 Share Posted August 27, 2012 Ok, to atone for providing such a long winded example, and as I've learned something from Salathe's super dooper example, here is a slimmed down version micahel that will produce a multidimensional array of all the time intervals: <?php $data_url = 'http://www.amecim.com/metronashvillewater/metronashvilleraingaugeservice.asmx/getAllGaugesAllIntervals'; $package = new SimpleXMLElement($data_url, NULL, TRUE); $topLevel = array(); foreach($package->children() as $k=>$gauge) { $topLevel[$k] = array( 'FifteenMinute' =>get_object_vars($gauge->FifteenMinute), 'ThirtyMinute' =>get_object_vars($gauge->ThirtyMinute), 'OneHour' =>get_object_vars($gauge->OneHour), 'TwoHour' =>get_object_vars($gauge->TwoHour), 'FourHour' =>get_object_vars($gauge->FourHour), 'SixHour' =>get_object_vars($gauge->SixHour), 'TwelveHour' =>get_object_vars($gauge->TwelveHour), 'TwentyfourHour' =>get_object_vars($gauge->TwentyfourHour) ); } // topLevel should be an array of all your interval values echo "<pre>"; print_r($topLevel); ?> Hope that helps and sorry my first attempt to help was a bit...well...crap Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373029 Share on other sites More sharing options...
salathe Posted August 28, 2012 Share Posted August 28, 2012 I guess you missed my entire point, there is no need to "convert" SimpleXMLElement objects into arrays (with get_object_vars(), casting, etc.) in order to use them. Learning how to work with SimpleXML will be much more beneficial than always working against it. It is really only a baby step of difference between using nested arrays and using SimpleXMLElement objects. Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373113 Share on other sites More sharing options...
Drongo_III Posted August 28, 2012 Share Posted August 28, 2012 Well I am keen to be enlightened. How would you suggest doing it? For instance if I remove the get_object_vars from one of the nested arrays in the foreach I get an array as follows (this is just a snippet because the array is huge) Array ( [bntCrk] => Array ( [FifteenMinute] => SimpleXMLElement Object ( [sampleDate] => 8-28-2012 [sampleTime] => 17:0:17 [GaugeName] => BntCrk [sampleValue] => 0 ) [ThirtyMinute] => Array ( [sampleDateStart] => 8-28-2012 [sampleDateEnd] => 8-28-2012 [sampleTimeStart] => 16:45:17 [sampleTimeEnd] => 17:0:17 [GaugeName] => BntCrk [sampleValueAccumulation] => 0 ) So the first nested array (FifteenMinute) is now an xml object. The second (ThirtyMinute) is a standard array because I've used get_object _vars to retrieve the values. You've suggested using get_object_vars in this scenario is incorrect but it's now simple to access the values, e.g.: echo $topLevel['BntCrk']['ThirtyMinute']['SampleDateStart']; So it would be quite easy to use this in an insert statement. But you've suggested this is wrong and it doesn't seem to be possible to do the following on the xml object nested array (probably because I can't seem to find out how you use the array when it's an xml object, so this is the bit i'm not getting): echo $topLevel['BntCrk']['FifteenMinute']['SampleDateStart']; So how do you access those values the proper way? Lets assume I want to insert that value into a database, or even simply echo it out. I am keen to learn Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373291 Share on other sites More sharing options...
salathe Posted August 28, 2012 Share Posted August 28, 2012 You're already doing it, in part, when calling get_object_vars(). If you haven't already, have a look over the SimpleXML Basic Usage page. $start = (string) $gauge->FifteenMinute->SampleDateStart; Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373313 Share on other sites More sharing options...
Drongo_III Posted August 28, 2012 Share Posted August 28, 2012 I see what you're saying there but lets say you want to get the children elements of FifteenMinutes, but each parent (e.g. FiftenMinutes, ThirtyMinutes etc.) has varying numbers of child elements. In that instance you can't precisely name the child elements as with: $start = (string) $gauge->FifteenMinute->SampleDateStart; So if you wanted to fill a miltidimensional array with the child elements of each time interval how would you cast the values then? Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373343 Share on other sites More sharing options...
salathe Posted August 28, 2012 Share Posted August 28, 2012 I guess I am not understanding your desire to stuff everything into a nested array. It is not needed and only making more work for yourself. Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373345 Share on other sites More sharing options...
Drongo_III Posted August 28, 2012 Share Posted August 28, 2012 Well the desire is to iterate over the entire xml document and for each place name pull out the child elements of the intervals in a form that can be: a) directly echoed to the page b) stored in a database The issue is if you have a variable number of child elements under each time interval you can't access the values directly (because you may not know what they are). So what is the best method of extracting the values from the time interval child elements in a form that can be used as outlined above? Sorry I don't mean to sound deliberately obtuse (or to be awkward), its just that using get_object_vars appears to do the above but you suggest it's incorrect. So I genuinely want to understand how it's possible to achieve the above without using get_object_vars or type casting if you don't know the end precise end element name. Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373349 Share on other sites More sharing options...
Christian F. Posted August 28, 2012 Share Posted August 28, 2012 You do know that you can loop over objects as if they were arrays, right? Quick example: foreach ($gauge->FifteenMinute as $sample) { echo $sample->SampleDateStart; } Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373358 Share on other sites More sharing options...
salathe Posted August 28, 2012 Share Posted August 28, 2012 foreach ($gauge->FifteenMinute as $sample) { echo $sample->SampleDateStart; } In this case, that's not particularly useful at all as there is only one <FifteenMinute> element per gauge. Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373363 Share on other sites More sharing options...
xyph Posted August 28, 2012 Share Posted August 28, 2012 Well the desire is to iterate over the entire xml document and for each place name pull out the child elements of the intervals in a form that can be: a) directly echoed to the page b) stored in a database The issue is if you have a variable number of child elements under each time interval you can't access the values directly (because you may not know what they are). So what is the best method of extracting the values from the time interval child elements in a form that can be used as outlined above? Sorry I don't mean to sound deliberately obtuse (or to be awkward), its just that using get_object_vars appears to do the above but you suggest it's incorrect. So I genuinely want to understand how it's possible to achieve the above without using get_object_vars or type casting if you don't know the end precise end element name. SimpleXML provides iteration through the class. There's no reason to convert it to an array only to iterate through it. Unknown values can be looped through. <?php $xml = new SimpleXMLElement('http://www.amecim.com/metronashvillewater/metronashvilleraingaugeservice.asmx/getAllGauges15m', 0, true); header('content-type: text/plain'); foreach( $xml as $location => $data ) { echo "$location\n"; foreach( $data->clsRainGaugeReading as $subdata ) { foreach( $subdata as $key => $value ) { echo "\t$key -> $value\n"; } } } ?> Quote Link to comment https://forums.phpfreaks.com/topic/267657-xml-parsing-assistance/#findComment-1373365 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.