如何正确地将字符串参数传递给 Oracle 中的 XPATH?

How to correctly pass a string argument to XPATH in Oracle?

如何将字符串参数传递给 EXTRACTVALUE

例如:

EXTRACTVALUE(fooColumn, '/foo/bar[@baz = "arg"]/@value')

如何用实参 :arg 替换 "arg"

天真的解决方案:

EXTRACTVALUE(fooColumn, '/foo/bar[@baz = "' || :arg || '"]/@value')

这里如何防止可能的“XPath”注入? 有没有XPath转义函数?

EXTRACTVALUE 已弃用,您应该改用 XMLQUERYXMLTABLE

您可以尝试使用 DBMS_ASSERT 包:

CREATE FUNCTION enquote_name (
  name IN VARCHAR2
) RETURN VARCHAR2
IS
BEGIN
  -- Wrap it in a function call to use the PL/SQL FALSE literal.
  RETURN DBMS_ASSERT.ENQUOTE_NAME(name, FALSE);
END;
/

然后:

SELECT XMLQUERY(
         ('/foo/bar[@baz='||ENQUOTE_NAME(:arg)||']/@value')
         PASSING fooColumn
         RETURNING CONTENT
       ) AS value
FROM   table_name

SELECT EXTRACTVALUE( foocolumn, '/foo/bar[@baz='||ENQUOTE_NAME(:arg)||']/@value')
         AS value
FROM   table_name

其中 table:

CREATE TABLE table_name ( foocolumn ) AS
SELECT XMLTYPE(
'<foo><bar baz="abc" value="123" /><bar baz="def" value="456" /></foo>'
)
FROM DUAL;

输出,当:argdef时:

VALUE
456

如果您尝试将 :arg 用作 'abc"][@value="123',则查询 returns 零行(或为 EXTRACTVALUE 引发异常);但是,如果您尝试传递相同的值而不将其包装在对 ENQUOTE_NAME 的调用中(并包括 ENQUOTE_NAME 将添加的双引号),那么它将执行您试图避免的 XPATH 注入。

db<>fiddle here