Skip to content

Commit

Permalink
XmlUtils.newPullParser: enable FEATURE_RELAXED if available (#44)
Browse files Browse the repository at this point in the history
* XmlUtils.newPullParser: enable FEATURE_RELAXED if available

* Added KDoc
  • Loading branch information
rfc2822 committed Apr 17, 2024
1 parent 6a0b597 commit b87d772
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/main/kotlin/at/bitfire/dav4jvm/Property.kt
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ interface Property {
log.log(Level.WARNING, "Ignoring invalid property", e)
}
}

eventType = parser.next()
}

Expand Down
46 changes: 37 additions & 9 deletions src/main/kotlin/at/bitfire/dav4jvm/XmlUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

package at.bitfire.dav4jvm

import at.bitfire.dav4jvm.exception.DavException
import at.bitfire.dav4jvm.exception.InvalidPropertyException
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException
Expand All @@ -15,18 +16,45 @@ import java.io.IOException

object XmlUtils {

private val factory: XmlPullParserFactory
init {
/**
* Requests the parser to be as lenient as possible when parsing invalid XML.
*
* See [https://www.xmlpull.org/](xmlpull.org) and specific implementations, for instance
* [Android XML](https://developer.android.com/reference/android/util/Xml#FEATURE_RELAXED)
*/
private const val FEATURE_RELAXED = "http://xmlpull.org/v1/doc/features.html#relaxed"

/** [XmlPullParserFactory] that is namespace-aware and does relaxed parsing */
private val relaxedFactory =
XmlPullParserFactory.newInstance().apply {
isNamespaceAware = true
setFeature(FEATURE_RELAXED, true)
}

/** [XmlPullParserFactory] that is namespace-aware */
private val standardFactory: XmlPullParserFactory =
XmlPullParserFactory.newInstance().apply {
isNamespaceAware = true
}

/**
* Creates a new [XmlPullParser].
*
* First tries to create a namespace-aware parser that supports [FEATURE_RELAXED]. If that
* fails, it falls back to a namespace-aware parser without relaxed parsing.
*/
fun newPullParser(): XmlPullParser =
try {
factory = XmlPullParserFactory.newInstance()
factory.isNamespaceAware = true
} catch (e: XmlPullParserException) {
throw RuntimeException("Couldn't create XmlPullParserFactory", e)
relaxedFactory.newPullParser()
} catch (_: XmlPullParserException) {
// FEATURE_RELAXED may not be supported, try without it
null
}
}
?: standardFactory.newPullParser()
?: throw DavException("Couldn't create XML parser")

fun newPullParser() = factory.newPullParser()!!
fun newSerializer() = factory.newSerializer()!!
fun newSerializer(): XmlSerializer = standardFactory.newSerializer()
?: throw DavException("Couldn't create XML serializer")


@Throws(IOException::class, XmlPullParserException::class)
Expand Down

0 comments on commit b87d772

Please sign in to comment.