你提供的关于你实际在做什么的细节很少,所以恐怕我只能猜测。
我无法重现您的错误消息,但我只尝试了几件事。也许您错误地调用了 Oracle XML API?也许您尝试解析的 XML 文档有些奇怪?恐怕我不知道,因为您没有向我们提供DOMSAMPLE
程序的来源,也没有向我们提供您尝试解析的 XML 文档。
我不敢相信您的程序的第 75 行是空白行。这是该过程的第 75 行,还是包含该过程的文件的第 75 行?
这是一个使用DBMS_XMLPARSER
and的示例DBMS_XMLDOM
。它只是读出给出的 XML 字符串的根元素的名称:
SET SERVEROUTPUT ON;
DECLARE
p dbms_xmlparser.parser;
d dbms_xmldom.domdocument;
e dbms_xmldom.domelement;
BEGIN
p := dbms_xmlparser.newParser;
dbms_xmlparser.parseBuffer(p, '<thisIsATest />');
d := dbms_xmlparser.getDocument(p);
e := dbms_xmldom.getDocumentElement(d);
dbms_output.put_line('Tag name is ' || dbms_xmldom.getTagName(e));
END;
/
当我运行它时,它会给我输出Tag name is thisIsATest
。
至于更简单的读取 XML 的方法,我之前回答的问题中有一个。我不知道这是否会对你有所帮助,因为我对你想要达到的目标知之甚少。
最后,请不要在SYS
模式中创建对象。
编辑:在您的评论中,您提到您使用dbms_xmlparser.parse
的是dbms_xmlparser.parseBuffer
. 在最终找到可行的方法之前,我dbms_xmlparser.parse
曾多次尝试并遇到相同的“无效的资源句柄或路径名”错误。以下是我设法开始工作的内容;对于您想要的东西,可能有比这更好的解决方案。
在您可以使用 Oracle 执行任何文件 I/O 之前,并且这似乎包括 using dbms_xmlparser.parse
,您必须首先创建一个 Oracle '目录'。Oracle 中的目录对应于文件系统上的目录。请注意,这是运行 Oracle 数据库的机器上的文件系统。如果 XML 文件不在同一个文件系统上(例如,Oracle 数据库在服务器上,而您的 XML 文件在您的开发 PC 上),您将无法使用dbms_xmlparser.parse
,除非您先将此文件传输到数据库服务器的文件系统。
我将首先创建一个与我的文件系统上的目录相对应的 Oracle 目录:
SQL> 创建或替换目录 ora_dir 为 '/home/luke/ora_dir';
已创建目录。
我在这里使用Linux。如果您使用的是 Windows,请随意反转斜线的方向。
在我们继续之前,让我们快速浏览一下我们将读入的 XML 文件:
SQL> 主机猫 /home/luke/ora_dir/example.xml
<?xml 版本="1.0" ?>
<根>
<孩子 />
</root>
在 SQL*Plus 中,host
将行的其余部分发送到 shell,或cmd.exe
在 Windows 上。在 Windows 上,您还可以使用type
而不是cat
.
最后,这是一个读取这个 XML 文件的 PL/SQL 块:
SQL> 设置服务器输出
SQL> 声明
2 p dbms_xmlparser.parser;
3d dbms_xmldom.domdocument;
4 e dbms_xmldom.dom 元素;
5 开始
6 p := dbms_xmlparser.newParser;
7 dbms_xmlparser.setBaseDir(p, 'ORA_DIR');
8 dbms_xmlparser.parse(p, 'example.xml');
9 d := dbms_xmlparser.getDocument(p);
10 e := dbms_xmldom.getDocumentElement(d);
11 dbms_output.put_line('标签名是' || dbms_xmldom.getTagName(e));
12 结束;
13 /
标签名称是根
PL/SQL 过程成功完成。
SQL>
这个块和更前面的块之间的唯一区别是调用的行dbms_xmlparser.parseBuffer
已被两行替换。这两行中的第一行调用dbms_xmlparser.setBaseDir
为解析器设置一个基本目录,第二行调用dbms_xmlparser.parse
使用相对于该目录的文件名。
编辑2:您的代码并没有像您希望的那样工作,并且您将其编辑到我的答案中,如下所示:
create or replace procedure printElements(doc xmldom.DOMDocument) is
nl xmldom.DOMNodeList;
len number;
n xmldom.DOMNode;
e xmldom.DOMElement;
nodeval varchar2(100);
begin
-- get all elements
nl := xmldom.getElementsByTagName(doc, '*');
len := xmldom.getLength(nl);
-- loop through elements
for i in 0..len-1 loop
n := xmldom.item(nl, i);
e := xmldom.makeElement(n => n);
dbms_output.put(xmldom.getNodeName(n) || ' ');
nodeval := xmldom.getNodeValue(n);
-- here nodeval i am getting as null, what mistake am doing?
dbms_output.put_line(' Value: '|| nodeval );
end loop;
dbms_output.put_line('');
end printElements;
正如三条评论中的最后一条所建议的那样,这显然将所有值都返回为 null。
引用我之前对类似问题的回答:
在 XML DOM 中,元素没有任何“价值”可言。元素节点包含作为子节点的文本节点,正是这些节点包含您想要的值。
所以,尝试更换线路
nodeval := xmldom.getNodeValue(n);
和
nodeval := xmldom.getNodeValue(xmldom.getFirstChild(n));