In this video I’ll take the Android Translation app I made in part 14 and now get it to parse XML data. I’m also going to add the ability to provide XML from the web service I made in part 5 of my web services tutorial.
This is an example of the techniques I use to make a professional app. We need to use multiple languages like Java, PHP and MySQL. All of the code in the video follows below. Feel free to do anything with it.
If you like videos like this, it would help if you shared on Google Plus with a click here [googleplusone]
Code From the Video
translateit.php
<?php
header('Content-Type:text/html; charset=UTF-8');
function translate($translate_to, $matching_ids, $dbc){
// Represents the id name in the table so for Russian it
// would be russian_id
$translate_id = $translate_to . '_id';
/* OLD QUERY THAT DELETES DUPLICATES
SELECT word FROM russian WHERE russian_id in (131,26,69)
ORDER BY CASE russian_id
WHEN 131 THEN 1
WHEN 26 THEN 2
WHEN 69 THEN 3
WHEN 26 THEN 4
END;
NEW TRANSLATE QUERY
SELECT russian.word
FROM russian
JOIN(
SELECT 131 AS id, 1 AS word_order
UNION ALL SELECT 26, 2
UNION ALL SELECT 26, 3
UNION ALL SELECT 69, 4) WordsToSearch ON russian.russian_id = WordsToSearch.id
ORDER BY WordsToSearch.word_order;
*/
$translate_query = 'SELECT word FROM ' . $translate_to . ' JOIN(' .
'SELECT ' . $matching_ids[0] . ' AS id, 1 AS word_order';
$array_size_2 = count($matching_ids);
for ($i = 1; $i < $array_size_2; $i++) {
$translate_query = $translate_query . " UNION ALL SELECT '" . $matching_ids[$i] .
"', " . ($i + 1) . " ";
}
$translate_query = $translate_query . ') WordsToSearch ON ' .
$translate_to . '.' . $translate_id . ' = WordsToSearch.id
ORDER BY WordsToSearch.word_order;';
// END OF NEW TRANSLATE QUERY
// Issue the query to the database
$translate_response = mysqli_query($dbc, $translate_query);
if($translate_response){
while($row = mysqli_fetch_array($translate_response)){
$translated_text = $translated_text . ' ' . $row['word'];
}
}
return $translated_text;
} // Close function translate
function get_translation($translate_to, $english_words){
// Trim white space from the name and store the name
$english_words = trim($english_words);
$english_array = array();
// Break the words into an array
$english_array = explode(" ", $english_words);
// Get a connection to the database
include('../mysqli_connect_language.php');
// Set character set in PHP to get proper characters
$dbc->set_charset("utf8");
/*
OLD QUERY THAT DELETES DUPLICATES
select english_id, word from english where word in ("Here", "are", "are", "dogs")
order by CASE word
WHEN "here" then 1
WHEN "are" then 2
WHEN "are" then 3
WHEN "dogs" then 4
END;
BEGINNING OF THE NEW QUERY -------------
UNION ALL combines the result set of multiple SELECT statements
which makes sure we receive all rows even if there are
duplicates
SELECT english.word
FROM english
JOIN (
SELECT 'A' AS word, 1 AS word_order
UNION ALL SELECT 'dog', 2
UNION ALL SELECT 'a', 3
UNION ALL SELECT 'cat', 4) WordsToSearch ON english.word = WordsToSearch.word
ORDER BY WordsToSearch.word_order;
*/
$query = "SELECT english_id, english.word FROM english JOIN(
SELECT '" . $english_array[0] . "' AS word, 1 AS word_order";
// Get the size of the array
$array_size = count($english_array);
for ($i = 1; $i < $array_size; $i++) {
$query = $query . " UNION ALL SELECT '" . $english_array[$i] .
"', " . ($i + 1) . " ";
}
$query = $query . ") WordsToSearch ON english.word = WordsToSearch.word
ORDER BY WordsToSearch.word_order;";
// END OF THE NEW QUERY -------------------
// Issue the query to the database
$response = @mysqli_query($dbc, $query);
// Array that contains the matching ids in order
$matching_ids = array();
if($response){
while($row = mysqli_fetch_array($response)){
$matching_ids[] = $row['english_id'];
// Holds the array after the select
$array_after_query[] = $row['word'];
}
} // Close if($response)
return translate($translate_to, $matching_ids, $dbc);
}
function get_all_translations($english_words){
$language_array = array("arabic", "chinese", "danish", "dutch",
"french", "german", "italian", "portuguese",
"russian", "spanish");
$translations_array = array();
foreach($language_array as $language){
$translations_array[] = get_translation($language,
$english_words);
}
$all_translations = '{"translations": [';
$index = 0;
foreach($language_array as $language){
$all_translations = $all_translations . '{"' . $language .
'":"' . $translations_array[$index] . '"},';
$index++;
}
$all_translations = rtrim($all_translations, ",");
$all_translations = $all_translations . ']}';
return $all_translations;
}
// ---------------------- NEW STUFF ----------------------
function get_xml_translations($english_words){
// Used as the tag names that will surround each translation
$language_array = array("arabic", "chinese", "danish", "dutch",
"french", "german", "italian", "portuguese",
"russian", "spanish");
// Will hold all translations
$translations_array = array();
foreach($language_array as $language){
$translations_array[] = get_translation($language,
$english_words);
}
// Define that all data will be between 2 translations tags
$xml = new SimpleXMLElement("<translations />");
// Index for $language_array
$lang_index = 0;
// Take each translation and put it between the correct
// language tag
foreach($translations_array as $translation){
$xml->addChild($language_array[$lang_index], $translation);
$lang_index++;
}
// Generate a DOM document we can style
// A DOM Document represents an entire XML document
$dom = dom_import_simplexml($xml)->ownerDocument;
// State we want the data to be indented
$dom->formatOutput = true;
// saveXML converts the XML into a string to print
return $dom->saveXML();
}
// ---------------------- NEW STUFF ----------------------
if(isset($_GET["action"])){
switch($_GET["action"]){
case "translate":
$translate_to = $_GET["language"];
$english_words = urldecode($_GET["english_words"]);
$translate_text = get_translation($translate_to,
$english_words);
break;
case "translations":
$english_words = urldecode($_GET["english_words"]);
$translated_text = get_all_translations($english_words);
header('Content-Type:application/json; charset=UTF-8');
break;
// ---------------------- NEW STUFF ----------------------
case "xmltranslations":
$english_words = urldecode($_GET["english_words"]);
$translated_text = get_xml_translations($english_words);
header('Content-Type:text/xml; charset=UTF-8');
break;
// ---------------------- NEW STUFF ----------------------
}
}
echo $translated_text;
?>
MyActivity.java
package com.newthinktank.derekbanas.xmltranslates;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
public class MyActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
}
// Calls for the AsyncTask to execute when the translate button is clicked
public void onTranslateText(View view) {
EditText translateEditText = (EditText) findViewById(R.id.words_edit_text);
// If the user entered words to translate then get the JSON data
if(!isEmpty(translateEditText)){
Toast.makeText(this, "Getting Translations",
Toast.LENGTH_LONG).show();
// ---------------------- NEW STUFF ----------------------
// Calls for the method doInBackground to execute
new GetXMLData().execute();
// ---------------------- NEW STUFF ----------------------
} else {
// Post an error message if they didn't enter words
Toast.makeText(this, "Enter Words to Translate",
Toast.LENGTH_SHORT).show();
}
}
// Check if the user entered words to translate
// Returns false if not empty
protected boolean isEmpty(EditText editText){
// Get the text in the EditText convert it into a string, delete whitespace
// and check length
return editText.getText().toString().trim().length() == 0;
}
// ---------------------- NEW STUFF ----------------------
// Allows you to perform background operations without locking up the user interface
// until they are finished
// The void part is stating that it doesn't receive parameters, it doesn't monitor progress
// and it won't pass a result to onPostExecute
class GetXMLData extends AsyncTask<Void, Void, Void>{
// Will hold the final string to display
String stringToPrint = "";
@Override
protected Void doInBackground(Void... voids) {
// Holds the xml String that is retrieved from the web service
String xmlString = "";
// Holds the words the user wants to translate
String wordsToTranslate = "";
// Where the user enters the words to translate
EditText translateEditText = (EditText) findViewById(R.id.words_edit_text);
// Get the words the user entered in the EditText box
wordsToTranslate = translateEditText.getText().toString();
// Replace spaces with plus so they can be passed in the URL to the web service
wordsToTranslate = wordsToTranslate.replace(" ", "+");
// Client used to grab data from a provided URL
DefaultHttpClient httpClient = new DefaultHttpClient(new BasicHttpParams());
// Provide the URL for the post request
HttpPost httpPost = new HttpPost("http://newjustin.com/translateit.php?action=xmltranslations&english_words=" + wordsToTranslate);
// Define that the data expected is in JSON format
httpPost.setHeader("Content-type", "text/xml");
// Allows you to input a stream of bytes from the URL
InputStream inputStream = null;
try {
// The client calls for the post request to execute and sends the results back
HttpResponse response = httpClient.execute(httpPost);
// Holds the message sent by the response
HttpEntity entity = response.getEntity();
// Get the content sent
inputStream = entity.getContent();
// A BufferedReader is used because it is efficient
// The InputStreamReader converts the bytes into characters
// My JSON data is UTF-8 so I read that encoding
// 8 defines the input buffer size
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"), 8);
// Storing each line of data in a StringBuilder
StringBuilder sb = new StringBuilder();
String line = null;
// readLine reads all characters up to a \n and then stores them
while((line = reader.readLine()) != null){
sb.append(line);
}
// Save the results to a String
xmlString = sb.toString();
// Generates an XML parser
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
// The XML parser that is generated will support XML namespaces
factory.setNamespaceAware(true);
// Gathers XML data and provides information on that data
XmlPullParser xpp = factory.newPullParser();
// Input the XML data for parsing
xpp.setInput(new StringReader(xmlString));
// The event type is either START_DOCUMENT, END_DOCUMENT, START_TAG,
// END_TAG, TEXT
int eventType = xpp.getEventType();
// Cycle through the XML document until the document ends
while (eventType != XmlPullParser.END_DOCUMENT) {
// Each time you find a new opening tag the event type will be START_TAG
// We want to skip the first tag with the name translations
if ((eventType == XmlPullParser.START_TAG) && (!xpp.getName().equals("translations"))) {
// getName returns the name for the current element with focus
stringToPrint = stringToPrint + xpp.getName() + " : ";
// getText returns the text for the current event
} else if (eventType == XmlPullParser.TEXT) {
stringToPrint = stringToPrint + xpp.getText() + "\n";
}
// next puts focus on the next element in the XML doc
eventType = xpp.next();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
// ---------------------- NEW STUFF ----------------------
@Override
protected void onPostExecute(Void aVoid) {
TextView translateTextView = (TextView) findViewById(R.id.translate_text_view);
translateTextView.setText(stringToPrint);
}
}
}
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.newthinktank.derekbanas.xmltranslates" >
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MyActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
activity_my.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MyActivity">
<EditText
android:id="@+id/words_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<Button
android:id="@+id/translate_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/words_edit_text"
android:layout_alignParentLeft="true"
android:layout_marginTop="15dp"
android:text="@string/translate_button"
android:onClick="onTranslateText"/>
<TextView
android:id="@+id/translate_text_view"
android:text="@string/translate_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/words_edit_text"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginTop="65dp" />
</RelativeLayout>
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">XML Translates</string>
<string name="hello_world">Hello world!</string>
<string name="action_settings">Settings</string>
<string name="translate_text_view">Enter the words to translate above</string>
<string name="translate_button">Translate</string>
</resources>
Hi Derek:
Iām Gokulraj 32 from India. I am physics graduate and work as a medical transcriptionist.
I don’t have any CS background and want to move to programming. I have begun teaching myself by reading stuff on the Web here and there.
Can you help me chart out definite plan for teaching myself. Where to begin, which books to read, etc.
Your guidance would be of immense help.
Thanks.
Hi,
It is best to start with a language like Python. I have a tutorial here on Python and I’ll make a learn python in 30 minutes tutorial next week. If you want to make Android apps, I made a tutorial for beginner programmers here as well. I hope they help š Have fun