Kotlin/Native Cinterop 与 libxml2 - 损坏的 XPath 表达式

问题描述 投票:0回答:1

版本

  • 科特林 1.9.22
  • libxml 2.9.14+dfsg-1.3
  • 操作系统:Ubuntu 23.10

问题

在一个小型 Kotlin/Native 应用程序中,我使用 cinterop 和

libxml2
来计算一组 XPath 表达式以提取元素文本和属性值。我以为我已经弄清楚了,但几周后,我的一个测试“突然”失败了:libxml 抱怨 XPath 无效。我在测试代码周围添加了一个循环,实际上,如果有足够的迭代,测试总是会失败。而且它总是在同一个 XPath 表达式(一组 4 个)上失败。这是我可以重现错误的最少代码:

@OptIn(ExperimentalForeignApi::class)
fun getElementTextFake(xml: String, xPathToNode: String): Either<XmlError, String> {
    val xPathCValues = xPathToNode.encodeToByteArray().toUByteArray().toCValues()
    val doc: xmlDocPtr? = xmlReadDoc(cur = xml.trim().encodeToByteArray().toUByteArray().toCValues(), URL = null, encoding = "UTF-8", options = 0)
    val xPathCtx: xmlXPathContextPtr? = doc?.let { xmlXPathNewContext(doc = it) }
    val xPathObj: xmlXPathObjectPtr? = xPathCtx?.let { xmlXPathEvalExpression(str = xPathCValues, ctxt = it) }
    val nodeSet: xmlNodeSetPtr? = xPathObj?.pointed?.nodesetval

    val result =
        if (nodeSet == null || nodeSet.pointed.nodeNr == 0) ElementNotFound(xPathToNode, xml).left() else "fakeElementText".right()

    xmlXPathFreeObject(xPathObj)
    xmlXPathFreeContext(xPathCtx)
    xmlFreeDoc(doc)

    return result
}

libxml2打印的错误是

XPath error : Invalid expression<br>
//*[local-name()='request']/*[local-name()='processing']P

传入的原始XPath表达式为

//*[local-name()='request']/*[local-name()='processing']

注意表达式字符串末尾的

P
,这使其无效。我的其他 XPath 表达式都不包含大写 P。错误几乎总是在几百次迭代内发生。

测试以单线程运行。

什么可能导致 XPath 表达式字符串的数据损坏?

kotlin xpath libxml2 kotlin-native cinterop
1个回答
0
投票

问题似乎出在字节数组上:

val xPathCValues = xPathToNode.encodeToByteArray().toUByteArray().toCValues()

libxml 似乎依赖于

xmlChar
数组以 0 结尾,以便找到输入的结尾。在数组末尾添加一个零元素解决了这个问题:

val xPathCValues = (xPathToNode.encodeToByteArray().toUByteArray() + 0u).toCValues()

如果需要 0 终止,则在字节数组中附加 0 可以解决该问题。但它并不能解释问题看似随机的本质。

© www.soinside.com 2019 - 2024. All rights reserved.