我正在构建一个工具,该工具可以根据上传到该工具的 zip 文件中的 XML 文件自动检测是否遵循了某些最佳实践。此工具使用 XPATH 解析 XML 并确定是否满足所有预定义条件。该工具检查的标准之一是某些对象(XML 文件)是否包含名为“loggedInUser()”的函数。我试图通过使用下面的 XPATH 来实现这一点:
计数(//节点/节点//文本()[包含(文本(),'loggedInUser()')])= 0
显着简化的示例 XMPL 文件如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<processModelHaul>
<pm>
<nodes>
<node>loggedInUser()</node>
<node></node>
<node></node>
<node></node>
<node></node>
<node></node>
</nodes>
</pm>
</processModelHaul>
我遇到的挑战是开发人员可以上传很多这些文件,而且这些文件比我上面放的示例要大得多。因此,当我遍历所有文件并使用上面的 XPATH 函数时,它需要很长时间并且我遇到了超时问题。
有什么方法可以优化上面的 XPATH 表达式以使其运行得更快吗?
编辑
我用来调试代码的 MariaDB 中的 SQL 查询是:
SELECT
`CR_getXpathOutput`(`RO`.`OBJECT_CONTENT`, `C`.`XPATH`) AS `CRITERIA`
FROM
`CR_REVIEW_OBJECT` `RO`
JOIN `CR_CRITERIA` `C` ON
`C`.`OBJECT_TYPE` = `RO`.`OBJECT_TYPE` AND SUBMISSION_ID=127 AND IS_ACTIVE=1 AND C.OBJECT_TYPE='Process Model' AND C.DISPLAY_VALUE='loggedInUser() detected'.
RO.OBJECT_CONTENT 是 XML 文件,C.XPATH 是来自 table CR_CRITERIA 的表达式 (//nodes/node[text()='loggedInUser()'])[1]。 CR_CRITERIA 是一个参考数据table,我在其中维护不同的XPATH。这里 CR_getXpathOutput 是一个函数,定义如下:
创建函数
CR_getXpathOutput
(ky
LONGTEXT,xpath
TEXT) 返回文本字符集 utf8 DETERMINISTIC BEGIN RETURN CAST( EXTRACTVALUE(ky, xpath) AS CHAR );结束
回答1
首先:将问题中的 XPath 更改为:
count(//nodes/node//text()[contains(., 'loggedInUser()')]) = 0
因此,将 contains-function 中的 text()
替换为 .
,因为您已经在该上下文中。
我不会使用 count 而是反过来做。如果你找到了,就让引擎停止搜索。因此它不必做所有的 xml。
如果您显示的 xml 结构始终相同,这意味着文本 loggedInUser()
将始终位于此 XPath: /processModelHaul/pm/nodes/node
中,并且该节点没有任何其他文本,则使用此 XPath:
(/processModelHaul/pm/nodes/node[text()='loggedInUser()'])[1]
如果该节点可以在任何地方但总是有一个父节点,请使用此 XPath:
(//nodes/node[text()='loggedInUser()'])[1]
如果在 MySql/MariaDB 中使用,您可以尝试:
not(exists(//nodes/node[text()='loggedInUser()'))