user16298059
user16298059

Reputation:

Kotlin reading children of XML

I can read DeckName,NumberOfCards & Introduction, but how do I read Card_0 without having to give the children of Card_0 index numbers, which I could in theory do but there has to be a better way than that?

Card_0 is just used for an example; I haven't included a loop in code because until I can read the children of Card_# it's pretty pointless putting it into a loop eg. get card by "Card_$i"

?xml version='1.0' encoding='UTF-8' standalone='yes' ?>
<root><DeckName>MelsDeckNoMedia</DeckName>
<NumberOfCards>42</NumberOfCards>
<Introduction>Some Text</Introduction>

<Card_0>
<Title>Title of Card</Title>
<Message></Message>
<Link>Name</Link>
<Timer>00:00:00</Timer>
<RollDice>false,</RollDice>
<CardImageURI>content://media/external/images/media/17233</CardImageURI>
<Math></Math>
<Questions></Questions>
<SkipPassword>false,</SkipPassword>
<AnimImageURI>content://media/external/images/media/17321</AnimImageURI>
<AnimImageAttributes>false,0,</AnimImageAttributes>
<FullScreenImageURI></FullScreenImageURI>
<FullScreenAttributes></FullScreenAttributes>
<VideoURI></VideoURI>
<VideoAttributes></VideoAttributes>
<AudioURI></AudioURI>
<AudioAttributes>0</AudioAttributes>
</Card_0>

<Card_1>
<Title></Title>
<Message></Message>
<Link></Link>
<Timer>00:00:00</Timer>
<RollDice>false,6</RollDice>
<CardImageURI>content://media/external/images/media/17233</CardImageURI>
<Math></Math>
<Questions></Questions>
<SkipPassword>false,</SkipPassword>
<AnimImageURI></AnimImageURI>
<AnimImageAttributes>false,0,</AnimImageAttributes>
<FullScreenImageURI></FullScreenImageURI>
<FullScreenAttributes></FullScreenAttributes>
<VideoURI></VideoURI>
<VideoAttributes></VideoAttributes>
<AudioURI></AudioURI>
<AudioAttributes>0</AudioAttributes>
</Card_1>

<Card_2>
<Title></Title>
<Message></Message>
<Link></Link>
<Timer>00:00:00</Timer>
<RollDice>true,6</RollDice>
<CardImageURI>content://media/external/images/media/17233</CardImageURI>
<Math></Math>
<Questions></Questions>
<SkipPassword>false,</SkipPassword>
<AnimImageURI></AnimImageURI>
<AnimImageAttributes>false,0,</AnimImageAttributes>
<FullScreenImageURI></FullScreenImageURI>
<FullScreenAttributes></FullScreenAttributes>
<VideoURI></VideoURI>
<VideoAttributes></VideoAttributes>
<AudioURI></AudioURI>
<AudioAttributes>0</AudioAttributes>
</Card_2>
</root>




//----------------------------------------------------------------------------------------------------
// XML get value by tag
//----------------------------------------------------------------------------------------------------
private fun readXMLTagValue( element: Element,tag : String ) : String {
    val nodeList = element.getElementsByTagName(tag).item(0).childNodes
    val node = nodeList.item(0)
    return node.nodeValue
}


//----------------------------------------------------------------------------------------------------
// Save Deck (Properties)
//----------------------------------------------------------------------------------------------------
fun loadDeckAsXML(appContext: Context,userpath : Uri,userfilename : String) {

    val file = File (userpath.toString(),userfilename)

    mytools.debug("loadDeckAsXML = ${userpath},${userfilename},output = $file")

    appContext.contentResolver.openInputStream(file.toUri()).use { inStream ->
        loadDeckFileXMLIO(appContext,inStream as FileInputStream)
    }

}

//----------------------------------------------------------------------------------------------------
// Load Deck File as XML
//----------------------------------------------------------------------------------------------------
private fun loadDeckFileXMLIO(appContext: Context, fis: FileInputStream) {

    try {
        val dbFactory = DocumentBuilderFactory.newInstance()
        val dBuilder = dbFactory.newDocumentBuilder()
        val doc = dBuilder.parse(fis)
        val element = doc.documentElement
        element.normalize()

        mydeckio.deckName = readXMLTagValue( element ,"DeckName" )
        mydeckio.deckNCards = readXMLTagValue( element ,"NumberOfCards" )
        mydeckio.deckIntroText = readXMLTagValue( element ,"Introduction" )

    } catch (e: FileNotFoundException) {
        Toast.makeText(appContext,"Deck file cannot be loaded", Toast.LENGTH_SHORT).show()
    } catch (e: IOException) {
        Toast.makeText(appContext,"IOEXCeption", Toast.LENGTH_SHORT).show()
    } finally {
        if (null != fis) {
            try {
                fis.close()
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }
}

Upvotes: 0

Views: 632

Answers (1)

absolute_vijju
absolute_vijju

Reputation: 51

Use this code

private fun parseXml() {
    val stringBuilder = StringBuilder()
    
    //        1. Get document builder
    val documentBuilderFactory = DocumentBuilderFactory.newInstance()
    val documentBuilder = documentBuilderFactory.newDocumentBuilder()

    //        2. Get document
    val inputStream = assets.open("yourfile.xml")
    val document = documentBuilder.parse(inputStream)

    //        3. Normalize the xml structure
    document.documentElement.normalize()

    //        4. Get all element by tag name
    val usersNodeList = document.getElementsByTagName("root")

    for (userIndex in 0 until usersNodeList.length) {

        val userNode = usersNodeList.item(userIndex)

        if (userNode.nodeType == Node.ELEMENT_NODE) {

            val userElement = userNode as Element

            val userDataList = userElement.childNodes

            for (userDataIndex in 0 until userDataList.length) {
                val userData = userDataList.item(userDataIndex)
                if (userData.nodeType == Node.ELEMENT_NODE) {
                    val userDataElement = userData as Element

                    if (userDataElement.tagName.startsWith("Card")) {

                        stringBuilder.append(userDataElement.tagName + ": " + getValue(userDataElement) + "\n")

                        val newList = userDataElement.childNodes

                        for (newListIndex in 0 until newList.length) {
                            val newData = newList.item(newListIndex)

                            if (newData.nodeType == Node.ELEMENT_NODE) {
                                val newUserDataElement = newData as Element
                                if (newUserDataElement.childNodes.length == 0)
                                    stringBuilder.append(newUserDataElement.tagName + ": " + "NA" + "\n")
                                else
                                    stringBuilder.append(newUserDataElement.tagName + ": " + getValue(newUserDataElement) + "\n")

                            }
                        }
                    } else
                        stringBuilder.append(userDataElement.tagName + ": " + getValue(userDataElement) + "\n")
                }
            }

        }
    }
    Log.d("mydata", stringBuilder.toString())

}


private fun getValue(element: Element): String {
    val nodeList = element.childNodes
    val node = nodeList.item(0)
    return node.nodeValue
}

Upvotes: 0

Related Questions