Starting Electronics needs your help! Please make a donation to help cover our hosting and other costs. Click the donate button to send a donation of any amount.
Created on: 15 June 2015
This is a much improved version of the Arduino cricket score ticker to display live cricket scores from the Internet.
This version of the cricket score ticker first captures the live cricket score XML file and saves it to SD card, then parses the saved XML file to extract the required score and game information.
The advantage of saving the XML file to SD card is that the file can be randomly accessed for the required information rather than trying to parse the incoming data on-the-fly as the previous version of the ticker tried to do (link above to previous version).
Similar projects that require an XML file to be parsed by an Arduino can be developed using the same XML parsing functions used in this project.
The Arduino sketch for the SD card ticker can be found below with an explanation of how the sketch and XML parsing functions work.
The sketch is too big to fit into the memory of an Arduino Uno, so an Arduino MEGA or similar Arduino with more memory than the Uno is required. To get some perspective on Arduino sketch sizes, see this blog.startingelectronics.com/a-comparison-of-arduino-sketch-sizes-in-memory/ (no longer available) blog post on Arduino sketches and memory used on an Arduino Uno.
Below is a list of the hardware and software used for developing this project. Similar compatible hardware should also work.
Copy the sketch below and paste it to the Arduino IDE. Load the sketch to an Arduino MEGA with Ethernet shield, SD card and Internet connection.
Open the Serial Monitor window of the Arduino IDE to see the available cricket matches – make sure that the Arduino Serial Monitor window baud rate is set to 115200. Enter the number of the match to view.
The cricket match information being viewed will be updated every 15 seconds. Sending M to the Arduino from the Serial Monitor window will display the menu of available matches again.
/* Gets the cricket score from synd.cricbuzz.com/j2me/1.0/livematches.xml * Saves the XML score file to SD card * Parses the XML file on the SD card for the desired data * All results are displayed in the Arduino IDE Serial Monitor window * * References and further information at: * http://startingelectronics.org/software/arduino/live-cricket-score-SD/ * * Author: W.A. Smith Date: 15 June 2015 */ #include <SPI.h> #include <Ethernet.h> #include <SD.h> // score refresh period in seconds #define REFRESH_PERIOD_SEC 15L byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; char server[] = "synd.cricbuzz.com"; IPAddress ip(192, 168, 0, 50); EthernetClient client; boolean currentLineIsBlank = true; // used to find end of incoming HTTP header File xmlFile; // handle of XML file stored on SD card char *file_name = "crick.xml"; // name of file the received XML is saved to on SD card int match_id = -1; // match to view, negative number means no match selected void setup() { // disable Ethernet chip pinMode(10, OUTPUT); digitalWrite(10, HIGH); // cricket match results are printed to the serial port // for display in the Arduino IDE Serial Monitor window, // so initialize the serial port Serial.begin(115200); if (!SD.begin(4)) { // SD card initialization failed return; } // delete old XML file if it exists if (SD.exists(file_name)) { SD.remove(file_name); } // start the Ethernet connection: if (Ethernet.begin(mac) == 0) { // try to congifure using IP address instead of DHCP: Ethernet.begin(mac, ip); } // give the Ethernet shield a second to initialize: delay(1000); } void loop() { // request the XML file at the set interval httpRequest(); // if there are incoming bytes available // from the server, strip the HTTP header // and save the incoming XML file if (client.available()) { char c = client.read(); if (c == '\n' && currentLineIsBlank) { // file to save the XML data to xmlFile = SD.open(file_name, FILE_WRITE); // end of received HTTP header, now save incoming bytes to XML file while (client.connected()) { // stay in this loop until all XML file bytes have been received if (client.available()) { // get the XML file bytes after the HTTP header c = client.read(); // replace all single quotes in the XML file with double quotes if (c == '\'') { c = '"'; } if (xmlFile) { // save the received byte to the XML file xmlFile.print(c); } } } // The XML file has been received and saved to SD card. // Display a menu of the matches from the SD card and // allow the user to choose which match details to // display. if (xmlFile) { // finished writing to the file, so close the file xmlFile.close(); // now open the file for reading xmlFile = SD.open(file_name, FILE_READ); if (xmlFile) { if (match_id < 0) { // a match has not been selected - bring up a menu for the user to select a match int num_matches; // number of matches in the XML file int match_selected = 0; // match selected by user, numbered 1 to num_matches char value[50] = {0}; // value read from XML file name / value pair // get the number of matches in the XML file num_matches = xmlGetNumTags("<match", "</mchdata>"); Serial.print(num_matches); Serial.println(F(" matches available, enter match number to view:")); // print the match menu for (int i = 0; i < num_matches; i++) { // start at the beginning of the file xmlFile.seek(0); // go to each <match> child tag inside parent <mchdata> tag if (xmlGoToChildTag("<match ", i + 1, "</mchdata>")) { Serial.print(i + 1); // match number in order found Serial.print(". "); // print the match series if (xmlGetTagNameValue("srs", value, 50)) { Serial.print(value); } // print the match description if (xmlGetTagNameValue("mchDesc", value, 50)) { Serial.print(" - "); Serial.println(value); } } } // get match number from user char rx_byte[2] = {0}; // user must enter match number from Serial Monitor window while (!rx_byte[0]) { if (Serial.available() > 0) { rx_byte[0] = Serial.read(); match_selected = atoi(rx_byte); // is the user entered match number valid? if ((match_selected < 1) || (match_selected > num_matches)) { // invalid match number Serial.println(F("Invalid, please enter match number.")); rx_byte[0] = 0; } else { // a match was selected from the menu, get the match ID // start at the beginning of the file xmlFile.seek(0); if (xmlGoToChildTag("<match", match_selected, "</mchdata>")) { if (xmlGetTagNameValue("id", value, 50)) { // The match ID number was found, save it as an integer. // The match will be accessed by match ID number to display the match // details in case the match changes position in the XML file. match_id = atoi(value); } } } } } } else { // A valid match was selected from the menu. // print the match parameters of the selected match PrintMatchData(match_id); } xmlFile.close(); } // finished with the file, so delete it SD.remove(file_name); } else { Serial.println(F("Error opening crick.xml")); } c = 0; } // detect the end of the incoming HTTP header if (c == '\n') { // starting a new line currentLineIsBlank = true; } else if (c != '\r') { // got a character on the current line currentLineIsBlank = false; } } // check for input from Serial Monitor window if (Serial.available() > 0) { char rx_opt = Serial.read(); // if user presses the M key, display the menu again if (rx_opt == 'm' || rx_opt == 'M') { // user requests match menu match_id = -1; Serial.println(F("\r\nNew menu will be printed after next data request.")); } } } // an example function that shows how to print the desired match parameters // customise this function to display the desired match parameters void PrintMatchData(int match_id) { char value[50] = {0}; // start at the beginning of the file xmlFile.seek(0); // go to the match of the specified match ID in the XML file if (xmlGoToTagID("<match", match_id)) { // get attributes from the <match> tag if (xmlGetTagNameValue("mchDesc", value, 50)) { Serial.print(F("Teams: ")); Serial.println(value); } if (xmlGetTagNameValue("srs", value, 50)) { Serial.print(F("Series: ")); Serial.println(value); } if (xmlGetTagNameValue("type", value, 50)) { Serial.print(F("Match Type: ")); Serial.println(value); } if (xmlGetTagNameValue("mnum", value, 50)) { Serial.print(F("Match Number: ")); Serial.println(value); } if (xmlGetTagNameValue("vcountry", value, 50)) { Serial.print(F("Country: ")); Serial.println(value); } if (xmlGetTagNameValue("vcity", value, 50)) { Serial.print(F("City: ")); Serial.println(value); } // get attributes from the <state> tag, child of the <match> tag if (xmlGoToChildTag("<state", 1, "</match>")) { if (xmlGetTagNameValue("status", value, 50)) { Serial.print(F("Match Status: ")); Serial.println(value); } if (xmlGetTagNameValue("mchState", value, 50)) { Serial.print(F("Match State: ")); Serial.println(value); } } } // only print the innings detail if the match is in progress // value must contain the match state if (strcmp(value, "inprogress") == 0) { // start at the beginning of the file xmlFile.seek(0); // get innings detail if (xmlGoToTagID("<match", match_id)) { if (xmlGoToChildTag("<mscr", 1, "</match>")) { if (xmlGoToChildTag("<inngsdetail", 1, "</mscr>")) { if (xmlGetTagNameValue("noofovers", value, 50)) { Serial.print(F("Number of overs: ")); Serial.println(value); } if (xmlGetTagNameValue("crr", value, 50)) { Serial.print(F("Current run rate: ")); Serial.println(value); } } } } xmlFile.seek(0); // get batting team details if (xmlGoToTagID("<match", match_id)) { if (xmlGoToChildTag("<mscr", 1, "</match>")) { if (xmlGoToChildTag("<btTm", 1, "</mscr>")) { if (xmlGetTagNameValue("sName", value, 50)) { Serial.print(F("Batting team: ")); Serial.println(value); } if (xmlGoToChildTag("<Inngs", 1, "</btTm>")) { if (xmlGetTagNameValue("r", value, 50)) { Serial.print(F("Runs: ")); Serial.println(value); } if (xmlGetTagNameValue("ovrs", value, 50)) { Serial.print(F("Overs: ")); Serial.println(value); } if (xmlGetTagNameValue("wkts", value, 50)) { Serial.print(F("Wickets: ")); Serial.println(value); } } } } } xmlFile.seek(0); // get bowling team details if (xmlGoToTagID("<match", match_id)) { if (xmlGoToChildTag("<mscr", 1, "</match>")) { if (xmlGoToChildTag("blgTm", 1, "</mscr>")) { if (xmlGetTagNameValue("sName", value, 50)) { Serial.print(F("Bowling team: ")); Serial.println(value); } } } } } } // Count the number of specified tags in the XML file // tag: tag to look for // end_tag: stop looking when this tag is found // returns: number of tags found specified by tag int xmlGetNumTags(char *tag, char *end_tag) { int num_tags = 0; // start at the beginning of the file xmlFile.seek(0); while (xmlFile.findUntil(tag, end_tag)) { num_tags++; } return num_tags; } // Go to the specified child tag in the XML file // tag: tag to find // tag_num: occurence number, e.g. 2 for second occurrence of tag // end_tag: closing tag that stops search, usually should be parent tag bool xmlGoToChildTag(char *tag, int tag_num, char *end_tag) { bool tag_found = false; int count = 0; while (xmlFile.findUntil(tag, end_tag)) { count++; if (count == tag_num) { tag_found = true; break; } } return tag_found; } // Get the value of the specified name / value pair of the current tag // The internal file pointer must be in the tag to search by using xmlGoToTagID() or xmlGoToChildTag() // attribute_name: input - name of the desired name value pair // attribute_value: output - value of the name / value pair read from file // val_len: input - length of attribute_value array // returns: true if requested attribute name is found // resets the internal file pointer to the position when the function was called bool xmlGetTagNameValue(char *attribute_name, char *attribute_value, int val_len) { bool name_found = false; char name_str[25] = {0}; int pointer_pos = 0; int bytes_read = 0; pointer_pos = xmlFile.position(); strcpy(name_str, attribute_name); strcat(name_str, "=\""); // put =" at end of attribute name if (xmlFile.findUntil(name_str, ">")) { bytes_read = xmlFile.readBytesUntil('\"', attribute_value, (val_len -1 )); attribute_value[bytes_read] = 0; // terminate the string name_found = true; } xmlFile.seek(pointer_pos); return name_found; } // move internal file pointer to tag with the specified id so that tag attributes can be read bool xmlGoToTagID(char *tag, int id) { bool tag_id_found = false; char str_buf[50] = {0}; int bytes_read; int id_read = 0; int pointer_pos = 0; while (xmlFile.find(tag)) { pointer_pos = xmlFile.position(); // found the tag, now find if the id name exists if (xmlFile.findUntil("id=\"", ">")) { // id name found, now get the id value bytes_read = xmlFile.readBytesUntil('\"', str_buf, 49); if (bytes_read) { // terminate the string str_buf[bytes_read] = 0; id_read = atoi(str_buf); if (id_read == id) { // the correct id has been found, now rewind the internal pointer to the beginning of the tag xmlFile.seek(pointer_pos); tag_id_found = true; break; } } } } return tag_id_found; } // this method makes a HTTP connection to the server: void httpRequest() { static unsigned long lastConnectionTime = 0; // last time connected to the server, in milliseconds static const unsigned long postingInterval = REFRESH_PERIOD_SEC * 1000L; // delay between updates, in milliseconds // the "L" is needed to use long type numbers // if specified time has elapsed since last connection, // then connect again and send request if (millis() - lastConnectionTime > postingInterval) { // close any connection before sending a new request client.stop(); if (client.connect(server, 80)) { Serial.println("\r\nconnected\r\n"); // Make a HTTP request: client.println("GET /j2me/1.0/livematches.xml HTTP/1.1"); client.println("Host: synd.cricbuzz.com"); client.println("Connection: close"); client.println(); // note the time that the connection was made: lastConnectionTime = millis(); } else { // didn't get a connection to the server: Serial.println(F("connection failed")); } } }
This video shows the cricket score ticker sketch running:
Can't see the video? View on YouTube →
You can help the Starting Electronics website by making a donation:
Any donation is much appreciated and used to pay the running costs of this website. Click the button below to make a donation.
The setup() function does the following initialization when the sketch starts running.
The setup() function first disables the W5100 Ethernet chip because the SPI bus is shared by the Ethernet chip and SD card. This ensures that data intended for the SD card does not get sent to the Ethernet chip.
The serial port baud rate is set to 115200. Match information is sent over the serial port and viewed in the Arduino IDE Serial Monitor window, so the serial port must first be initialized.
The SD card is used to save the XML file, so must be initialized. If the file on the SD card used for the incoming XML data exists from previously running the sketch it is deleted. The file is deleted because if it exists, it will not be overwritten, but rather new XML data will be appended to it.
Finally the Ethernet chip is initialized so that it can be used to request the XML file over the Internet.
The main loop connects to the cricket score website and requests the XML file using the httpRequest() function.
The httpRequest() function only sends a request for the XML file every 15 seconds, set by REFRESH_PERIOD_SEC at the top of the sketch.
In the main loop, the code looks for the incoming blank line that occurs after the HTTP header has been received. The bytes that come through after the HTTP header are the bytes that make up the XML file and are saved to the SD card.
A file is opened to save the XML bytes to and then all of the incoming bytes are saved inside the loop:
while (client.connected()) {
After the XML file bytes have been saved, the file is closed for writing to and then opened for reading.
If the a menu item has not been selected, or the user enters an invalid menu item number, the menu will be displayed. The default menu number is set to invalid by setting its value to -1.
Inside the following if statement the file is parsed to find the number of matches that it contains:
if (match_id < 0) {
A for loop is used to print the match menu.
After the match menu is printed, the code sits in the following loop waiting for the user to enter a valid match number in the serial monitor window:
while (!rx_byte[0]) {
When the user enters a valid match number, the match ID for the selected match is saved to the match_id variable.
Match numbers are assigned to matches in the order that they are found in the XML file. Each <match> tag in the file contains a match ID. The match ID is saved to the variable in case matches are added or removed from the XML file by the host site. By searching the file by match ID, the match can be moved to any position in the file and the correct match will be found.
The code that later prints out the match information and scores only accesses the match by match ID and not the order number that the match originally appeared in.
Once a valid match has been selected and the match ID saved, the PrintMatchData() function is used to extract the desired match data from the XML file and send it to the Serial Monitor window.
PrintMatchData() demonstrates how to get some of the selected match data and can be customized to print the desired match data.
With a valid match selected, the code will also check to see if M is sent to the Arduino from the serial monitor window which will bring up the match menu again.
The sketch requests an XML file that contains the live cricket score data from the CricBuzz website's http://synd.cricbuzz.com/j2me/1.0/livematches.xml (no longer working) live XML feed.
The following XML file was captured from CricBuzz's live feed.
<mchdata NMchs="11"> <links fUrlBase="http://synd.cricbuzz.com/j2me/1.0/flags/team_" /> <match id="3" type="TEST" srs="Australia tour of West Indies, 2015" mchDesc="WI vs AUS" mnum="2nd Test" vcity="Kingston, Jamaica" vcountry="West Indies" grnd="Sabina Park" inngCnt="4" datapath="http://synd.cricbuzz.com/j2me/1.0/match/2015/2015_WI_AUS/WI_AUS_JUN11_JUN15/" > <state mchState="complete" status="Aus won by 277 runs" TW="WI" decisn="Fielding" addnStatus="" splStatus=""> </state> <Tm id="10" Name="WI" sName="WI" flag='1'/> <Tm id="4" Name="Aus" sName="AUS" flag='1'/> <Tme Dt="Jun 11 2015" stTme="15:00" enddt ="Jun 15 2015" ></Tme> <mscr> <inngsdetail noofovers="0" rrr="0" crr="2.71" cprtshp=""/> <btTm id="10" sName="WI"> <Inngs desc="2nd Inns" r="114" Decl="0" FollowOn="0" ovrs="42" wkts="10"/> <Inngs desc="1st Inns" r="220" Decl="0" FollowOn="0" ovrs="59.5" wkts="10"/> </btTm> <blgTm id="4" sName="AUS"> <Inngs desc="2nd Inns" r="212" Decl="1" FollowOn="0" ovrs="65" wkts="2"/> <Inngs desc="1st Inns" r="399" Decl="0" FollowOn="0" ovrs="126.5" wkts="10"/> </blgTm> </mscr> </match> <match id="1" type="ODI" srs="New Zealand tour of England, 2015" mchDesc="ENG vs NZ" mnum="3rd ODI" vcity="Southampton" vcountry="England" grnd="The Rose Bowl" inngCnt="2" datapath="http://synd.cricbuzz.com/j2me/1.0/match/2015/2015_ENG_NZ/ENG_NZ_JUN14/" > <state mchState="complete" status="NZ won by 3 wkts" TW="Eng" decisn="Batting" addnStatus="" splStatus=""> </state> <Tm id="9" Name="Eng" sName="ENG" flag='1'/> <Tm id="13" Name="NZ" sName="NZ" flag='1'/> <Tme Dt="Jun 14 2015" stTme="09:30" enddt ="Jun 14 2015" ></Tme> <mscr> <inngsdetail noofovers="50" rrr="0" crr="6.24" cprtshp="6(5)"/> <btTm id="13" sName="NZ"> <Inngs desc="Inns" r="306" Decl="0" FollowOn="0" ovrs="49" wkts="7"/> </btTm> <blgTm id="9" sName="ENG"> <Inngs desc="Inns" r="302" Decl="0" FollowOn="0" ovrs="45.2" wkts="10"/> </blgTm> </mscr> </match> <match id="2" type="TEST" srs="India tour of Bangladesh, 2015" mchDesc="BAN vs IND" mnum="Only Test" vcity="Fatullah" vcountry="Bangladesh" grnd="Khan Shaheb Osman Ali Stadium" inngCnt="3" datapath="http://synd.cricbuzz.com/j2me/1.0/match/2015/2015_BAN_IND/BAN_IND_JUN10_JUN14/" > <state mchState="complete" status="Match drawn" TW="Ind" decisn="Batting" addnStatus="" splStatus=""> </state> <Tm id="6" Name="Ban" sName="BAN" flag='1'/> <Tm id="2" Name="Ind" sName="IND" flag='1'/> <Tme Dt="Jun 10 2015" stTme="04:00" enddt ="Jun 14 2015" ></Tme> <mscr> <inngsdetail noofovers="0" rrr="0" crr="1.53" cprtshp="23(90)"/> <btTm id="6" sName="BAN"> <Inngs desc="2nd Inns" r="23" Decl="0" FollowOn="1" ovrs="15" wkts="0"/> <Inngs desc="1st Inns" r="256" Decl="0" FollowOn="0" ovrs="65.5" wkts="10"/> </btTm> <blgTm id="2" sName="IND"> <Inngs desc="1st Inns" r="462" Decl="1" FollowOn="0" ovrs="103.3" wkts="6"/> </blgTm> </mscr> </match> <match id='14586' type="TEST" srs="Australia tour of West Indies, 2015" mchDesc="WI vs AUS" mnum="2nd Test" inngCnt="4" datapath="http://synd.cricbuzz.com/j2me/1.0/match/2015/2015_WI_AUS/WI_AUS_JUN11_JUN15/" > <state mchState="Result" status="Aus won by 277 runs"> </state> <manofthematch NoOfPlayers="1"> <mom Name="Steven Smith"/> </manofthematch> <ManOftheSeries NoOfPlayers="1"> <mos Name="Josh Hazlewood"/> </ManOftheSeries > <Tm id="10" Name="WI" sName="WI" flag='1'/> <Tm id="4" Name="Aus" sName="AUS" flag='1'/> <Tme Dt="Jun 11 2015" stTme="15:00" enddt ="Jun 15 2015"></Tme> </match> <match id='13747' type="ODI" srs="New Zealand tour of England, 2015" mchDesc="ENG vs NZ" mnum="3rd ODI" inngCnt="2" datapath="http://synd.cricbuzz.com/j2me/1.0/match/2015/2015_ENG_NZ/ENG_NZ_JUN14/" > <state mchState="Result" status="NZ won by 3 wkts"> </state> <manofthematch NoOfPlayers="1"> <mom Name="Kane Williamson"/> </manofthematch> <Tm id="9" Name="Eng" sName="ENG" flag='1'/> <Tm id="13" Name="NZ" sName="NZ" flag='1'/> <Tme Dt="Jun 14 2015" stTme="09:30" enddt ="Jun 14 2015"></Tme> </match> </mchdata>
The Arduino sketch uses the XML parsing functions (explained below) to move to specific tags inside the XML file and then get the value from a name / value pair within a tag.
An XML parsing function will first move the internal file pointer to the match tag of the desired ID. The XML below extracted from the above file shows the first match tag which has an ID of 3.
<match id="3"
The above XML file contains 5 matches, each with a unique match ID. The top level structure of the file is shown below where the XML file has been formatted for easier reading and the child tags of each match tag have been removed.
<mchdata NMchs="11"> <links fUrlBase="http://synd.cricbuzz.com/j2me/1.0/flags/team_" /> <match id="3" type="TEST" srs="Australia tour of West Indies, 2015" mchDesc="WI vs AUS" mnum="2nd Test" vcity="Kingston, Jamaica" vcountry="West Indies" grnd="Sabina Park" inngCnt="4" datapath="http://synd.cricbuzz.com/j2me/1.0/match/2015/2015_WI_AUS/WI_AUS_JUN11_JUN15/" > </match> <match id="1" type="ODI" srs="New Zealand tour of England, 2015" mchDesc="ENG vs NZ" mnum="3rd ODI" vcity="Southampton" vcountry="England" grnd="The Rose Bowl" inngCnt="2" datapath="http://synd.cricbuzz.com/j2me/1.0/match/2015/2015_ENG_NZ/ENG_NZ_JUN14/" > </match> <match id="2" type="TEST" srs="India tour of Bangladesh, 2015" mchDesc="BAN vs IND" mnum="Only Test" vcity="Fatullah" vcountry="Bangladesh" grnd="Khan Shaheb Osman Ali Stadium" inngCnt="3" datapath="http://synd.cricbuzz.com/j2me/1.0/match/2015/2015_BAN_IND/BAN_IND_JUN10_JUN14/" > </match> <match id='14586' type="TEST" srs="Australia tour of West Indies, 2015" mchDesc="WI vs AUS" mnum="2nd Test" inngCnt="4" datapath="http://synd.cricbuzz.com/j2me/1.0/match/2015/2015_WI_AUS/WI_AUS_JUN11_JUN15/" > </match> <match id='13747' type="ODI" srs="New Zealand tour of England, 2015" mchDesc="ENG vs NZ" mnum="3rd ODI" inngCnt="2" datapath="http://synd.cricbuzz.com/j2me/1.0/match/2015/2015_ENG_NZ/ENG_NZ_JUN14/" > </match> </mchdata>
We can see that the mchdata tag contains five match child tags. Each child tag contains attributes in the form of name / value pairs, for example type="TEST" is a name value pair where type is the name and TEST is the value.
To parse the file, first a function is called to move to the match tag with the desired ID. Once at the match tag, match data can be extracted from the tag's attributes.
Each match tag contains further child tags, which themselves may contain further child tags. The principle of operation is to find out if a child tag exists by moving to it. If the child tag exists and contains a child tag with the desired data, the internal file pointer is then moved to this child tag if it is found.
The same XML parsing function is called each time to move one child tag level deeper until the desired tag is found.
The above explanations give an overview of how the top level application works and a look at the structure of the XML file. XML parsing functions do the actual work of extracting or parsing the XML file data.
All the XML parsing functions access the XML file using the global file handle xmlFile and expect it to be a valid file handle.
xmlGoToTagID() and xmlGoToChildTag() are used to position the internal file pointer at the start of the desired tag which contains the cricket match data in name / value pairs. xmlGetTagNameValue() is then used to get the value of the name / value pair from the tag that the internal file pointer is at.
xmlGetNumTags() is used to find the number of occurrences of a specific tag and is used to find the the number of matches in the XML file by finding the number of match child tags inside the mchdata parent tag.
Usage in the sketch:
// get the number of matches in the XML file num_matches = xmlGetNumTags("<match", "</mchdata>");
This function moves the internal file pointer to the specified tag with the specified ID and is used to go to the match tag with the specified match ID.
Usage in the sketch:
// go to the match of the specified match ID in the XML file if (xmlGoToTagID("<match", match_id)) {
Moves the internal file pointer to the beginning of the specified child tag inside the specified parent tag.
This function must be called to move through child tags in the order that they occur. First to find a parent tag, then the child tag of the parent tag. If the child tag contains a further child tag, then the function must be called again to move to the child tag one level deeper.
Example usage from the sketch:
if (xmlGoToChildTag("<state", 1, "</match>")) {
This example goes to the first occurrence of the state child tag inside the match parent tag.
Gets the value of a name / value pair from the XML file. It expects the internal file pointer to be at the start of the tag to search for the name / value pair.
Move to the desired tag using either xmlGoToTagID() or xmlGoToChildTag() before calling xmlGetTagNameValue() so that the internal file pointer is at the tag to search.
This function moves the internal file pointer back to the beginning of the specified child tag name before it returns so that it can be called multiple times on a single tag even if the order of the name / value pairs is changed in the tag. In this way it can extract as much data as needed from multiple name / value pairs within a tag irrespective of the order in which the name / value pairs occur.
Usage example from the sketch:
// print the match series if (xmlGetTagNameValue("srs", value, 50)) { Serial.print(value); }
This example searches for the srs name in the match tag to get it's value. The internal file pointer was moved to the match tag using xmlGoToChildTag() before calling this function.
You can help the Starting Electronics website by making a donation:
Any donation is much appreciated and used to pay the running costs of this website. Click the button below to make a donation.
This project used the following resources:
As an Amazon Associate I earn from qualifying purchases: