Interviewer: How do you dynamically determine whether the data returned by the server is Xml or Json? (Answers below)
Hence the article.
1. What is XML
XML (Extensible Markup Language): XML is a markup language used to store and transfer data. The file name extension is.xml and is case sensitive. XML defines a set of rules for encoding documents in human-readable and machine-readable formats. XML was designed to focus on the simplicity, versatility, and usability of the Internet. It is a text data format and is recommended by the W3C with strong support for different human languages through Unicode. Such as:
<Users>
<user>
<name>James</name>
<age>18</age>
</user>
<user>
<name>Mike</name>
<age>19</age>
</user>
<user>
<name>John</name>
<age>20</age>
</user>
<user>
<name>Peter</name>
<age>21</age>
</user>
</Users>
Copy the code
1.1 Differences between XML and JSON
JSON (JavaScript Object Notation): A lightweight data interchange format that is completely language independent. It is based on the JavaScript programming language and is easy to understand and generate. The file name extension is. Json. Such as:
{
"Users":[
{
"name":"James"."age":18
},
{
"name":"Mike"."age":19
},
{
"name":"John"."age":20
},
{
"name":"Peter"."age":21}}]Copy the code
Differences between XML and JSON:
JSON | XML |
---|---|
Is a JavaScript object representation | Is an extensible markup language |
Based on JavaScript | Derived from SGML |
That’s one way to represent an object | Is a markup language and uses tag structures to represent data items |
JSON: string, number, array, Boolean | All XML data should be strings |
Do not use closing tags | Has start and end tags |
Only UTF-8 encoding is supported | Support for various encodings |
Compared to XML, its files are very easy to read and understand | Its documentation is relatively difficult to read and understand |
No support for namespaces is provided | It supports namespaces |
It’s less secure | It is more secure than JSON |
No comments supported | Support the review |
Since the reference:JSON vs XML: What’s the Difference? |
OK, back to the interview question above:
Interviewer: How do you dynamically determine whether the data returned by the server is Xml or Json? A: XML documents must start with “<“, so you only need to use this condition to determine. Such as: the if (s.s tartsWith (” < “)
2. How do YOU parse XML in Android
There are three ways to parse XML on Android:
- XmlPullParser
- Dom Parser
- SAX Parser
The following details three parsing methods and practice parsing the user_Info.xml file, parsing the contents, and displaying them. The user_info.xml file looks like this:
<Users>
<user>
<name>James</name>
<age>18</age>
</user>
<user>
<name>Mike</name>
<age>19</age>
</user>
<user>
<name>John</name>
<age>20</age>
</user>
<user>
<name>Peter</name>
<age>21</age>
</user>
</Users>
Copy the code
When the XML content is parsed out, it is displayed as follows:
Let’s take a look at the implementation of these three methods.
2.1 XmlPullParser
Android recommends using XMLPullParser to parse XML files because it is faster than SAX and DOM.
Methods:
- GetEventType () : returns the type of the current event (START_TAG, END_TAG, TEXT, etc.)
- GetName () : For START_TAG or END_TAG events, when namespaces are enabled, the (local) name of the current element, such as “Users”, “user”, “name”, “age”, is returned. When namespace processing is disabled, the original name is returned.
Event type:
- START_DOCUMENT: Indicates that the parser is at the beginning of the document, but has not yet read anything. This event type can only be observed if getEvent() is called before the first call to the next(), nextToken(), or nextTag() methods.
- END_DOCUMENT: Indicates that the parser is at the end of the document.
- START_TAG: indicates the start tag.
- END_TAG: indicates the end tag.
- TEXT: indicates the label content.
In the user_info.xml file, the mapping is as follows:
The concrete implementation steps are as follows:
- Instantiate an XmlPullParser and set it up to handle XML namespaces
- Enter the file data stream for the parser through the setInput() method
- Determine the event type, call the next() method for loop parsing, and extract the tag content through the getText() method until parsing to the end of the document, END_DOCUMENT
The specific code is as follows:
class XmlPullParseTestActivity : AppCompatActivity() {
private val userList: ArrayList<User> = ArrayList()
private var user: User = User()
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_xml_pull_parse_test)
xmlParseData()
}
private fun xmlParseData(a) {
try {
val inputStream: InputStream = assets.open(USER_INFO_XML_FILE)
val parserFactory =
XmlPullParserFactory.newInstance()
val parser = parserFactory.newPullParser()
// Set the XML parser to handle namespaces
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false)
// Sets the input stream that the parser will process, resetting the parser state and setting the event type to the initial value START_DOCUMENT
parser.setInput(inputStream, null)
// Returns the current event type
var eventType = parser.eventType
var parseContentText = ""
// Loop through parsing until you reach the end of the XML document
while(eventType ! = XmlPullParser.END_DOCUMENT) {// The namespace is started, so the local name of the current element is returned, such as "Users", "user", "name", "age".
val tagName = parser.name
when (eventType) {
XmlPullParser.START_TAG -> {
if (tagName == USER_TAG) user = User()
}
XmlPullParser.TEXT -> {
// Returns the text content of the current event as a String
parseContentText = parser.text
}
XmlPullParser.END_TAG -> {
when (tagName) {
NAME_TAG -> user.name = parseContentText
AGE_TAG -> user.age = parseContentText.toInt()
USER_TAG -> userList.add(user)
}
}
}
eventType = parser.next()
}
// Display parsed content data
for (user in userList) {
val textContent = "${xmlPullParseShowTv.text} \n\n" +
"Name: ${user.name} \n" +
"Age: ${user.age} \n" +
"------------------\n"
xmlPullParseShowTv.text = textContent
}
} catch (e: IOException) {
e.printStackTrace()
} catch (e: XmlPullParserException) {
e.printStackTrace()
}
}
}
Copy the code
2.2 the DOM Parser
Dom Parser creates and parses XML files using an object-based approach, directly accessing parts of XML documents. Dom parsers load XML files into memory to parse XML documents, which also consumes more memory (so you can’t use Dom parsers to parse large files). The XML document is parsed from the start node to the end node.
In the Dom parser, each tag in the XML file is an Element, and the contents of the Element are a Node. If there are more than one Node in the Element, a NodeList is formed.
The mapping in user_info.xml is as follows:
Specific implementation steps:
- Instantiate a DocumentBuilder object and enter the document data stream using the parse() method
- Get the document child node with the getDocumentElement() method, and get the NodeList under that TAG with getElementsByTagName(TAG)
- Loop through NodeList, determine the Node type, convert Node to Element, and then repeat the previous step to retrieve node. value (the tag)
Specific code:
class DomParseTestActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_dom_parse_test)
domParseData()
}
private fun domParseData(a) {
try {
val inputStream = assets.open(USER_INFO_XML_FILE)
val dbFactory = DocumentBuilderFactory.newInstance()
// Instantiate a DocumentBuilder object
val dBuilder = dbFactory.newDocumentBuilder()
// Parse the input stream into Document
val doc = dBuilder.parse(inputStream)
// Access the document element child node directly
val element = doc.documentElement
// Normalize the child node element
element.normalize()
// Retrieve all nodes under the 'user' tag
val nodeList = doc.getElementsByTagName(USER_TAG)
for (i in 0 until nodeList.length) {
val node = nodeList.item(i)
// Check if it is an element node type
if (node.nodeType == Node.ELEMENT_NODE) {
// Convert node to Element in order to get node data through getElementsByTagName()
val theElement = node as Element
// Display parsed content data
val textContent = "${domParseShowTv.text} \n\n" +
"Name: ${getValue(NAME_TAG, theElement)} \n" +
"Age: ${getValue(AGE_TAG, theElement)} \n" +
"------------------\n"
domParseShowTv.text = textContent
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
private fun getValue(tag: String, element: Element): String {
// Fetch the corresponding node according to the specified label
val nodeList = element.getElementsByTagName(tag).item(0).childNodes
val node = nodeList.item(0)
return node.nodeValue
}
}
Copy the code
2.3 the SAX Parser
SAX(Simple API for XML) : Is an event-based parser. Unlike DOM parsers, SAX parsers do not create any parse trees and receive notification of events that process elements in order, starting at the top of the document and ending at the end.
Advantages: We can instruct the SAX parser to stop halfway through the document without losing the collected data. Disadvantages: The XML document cannot be accessed randomly because it is processed in a forward-only fashion.
So when is it appropriate to use SAX Parser to parse XML files?
- You can process XML documents in a linear fashion from top to bottom.
- The XML document to be parsed has no deep nesting.
- You are dealing with a very large XML document whose DOM tree will consume too much memory. A typical DOM implementation uses 10 bytes of memory to represent a single byte of XML.
- The problem you have to solve involves only one part of the XML document, that is, you only need to parse a part of the XML file.
See: Java SAX Parser-Overview
The methods we want to implement are:
- StartDocument: Receives notification of the start of a document.
- EndDocument: Receives notification at the end of a document.
- StartElement: Receives notification of the start of the element.
- EndElement: Receives notification of the end of an element.
- Characters: receives notification of character data inside elements.
In the user_info.xml file, the mapping is as follows:
The concrete implementation steps are as follows:
- Instantiate a SAXParser object.
- Rewrite a DefaultHandler to implement the startElement, endElement, characters methods.
- The document input stream and Handler are passed to the SAXParser.parse() method for parsing.
class SaxParseActivity : AppCompatActivity() {
var userList: ArrayList<User> = ArrayList()
var user: User = User()
override fun onCreate(savedInstanceState: Bundle?). {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_sax_parse)
saxParseData()
}
private fun saxParseData(a) {
try {
val parserFactory: SAXParserFactory = SAXParserFactory.newInstance()
val parser: SAXParser = parserFactory.newSAXParser()
val inputStream: InputStream = assets.open(USER_INFO_XML_FILE)
Parses the content of the given input stream to XML using the specified DefaultHandler.
parser.parse(inputStream, Handler())
// Display parsed content data
for (user in userList) {
val textContent = "${saxParseShowTv.text} \n\n" +
"Name: ${user.name} \n" +
"Age: ${user.age} \n" +
"------------------\n"
saxParseShowTv.text = textContent
}
} catch (e: IOException) {
e.printStackTrace()
} catch (e: ParserConfigurationException) {
e.printStackTrace()
} catch (e: SAXException) {
e.printStackTrace()
}
}
inner class Handler : DefaultHandler() {
private var currentValue = ""
var currentElement = false
/** * file starts */
override fun startDocument(a) {
super.startDocument()
}
/** * End of document */
override fun endDocument(a) {
super.endDocument()
}
/** * element start * localName: Returns the label we defined, namely: "Users","user", "name", "age" */
override fun startElement(
uri: String? , localName:String? , qName:String? , attributes:Attributes?). {
super.startElement(uri, localName, qName, attributes)
// A new node, i.e. a new user node
currentElement = true
currentValue = ""
if (localName == USER_TAG) {
user = User()
}
}
/** * End of current element * localName: Returns the label we defined, namely: "Users","user", "name", "age" */
override fun endElement(uri: String? , localName:String? , qName:String?). {
super.endElement(uri, localName, qName)
// The current element is parsed
currentElement = false
when(localName) {
NAME_TAG -> user.name = currentValue
AGE_TAG -> user.age = currentValue.toInt()
// Add the first user to the userList
USER_TAG -> userList.add(user)
}
}
/** ** receives the internal character data of the element * ch: returns the contents of the label in the form of char[] * start: the initial Index of ch, that is, 0 * length: the length of the ch array */
override fun characters(ch: CharArray? , start:Int, length: Int) {
super.characters(ch, start, length)
if (currentElement) {
// Returns the contents of the label as a StringcurrentValue += String(ch!! , start, length) } } } }Copy the code
See Github: ParseXml for the full code in the above article
In fact, the biggest purpose of sharing articles is to wait for someone to point out my mistakes. If you find any mistakes, please point them out without reservation and consult with an open mind. In addition, if you think this article is good and helpful, please give me a like as encouragement, thank you ~ Peace~!
Reference Documents:
- Android XML Parsing using SAX Parser
- Android XML Parsing using DOM Parser
- Android XMLPullParser Tutorial
- Android- DOM parsing XML
- Android– PULL for parsing XML
- Android– SAX for parsing XML