-1

Oracle 数据库 10g 企业版 10.2.0.5 - 64bi

我正在尝试将我发现的元素的层次结构输出到使用祖先或自我的根,但它根本不起作用:只需打印所有元素(

好吧,我有什么:

1) 像这样的 XML 文件。

<Root>
  <Element1 id="UniqueId1">
    <SubElement1 id="UniqueId2"/>
    <SubElement2 id="UniqueId3">
      <LeafElement1 id="UniqueId4"/>
      <LeafElement1 id="UniqueId5"/>
    </SubElement2>
  </Element1>
  <Element2 id="UniqueId6" AttributeToCheck="true">
    <SubElement1 id="UniqueId7">
      <LeafElement1 id="UniqueId8"/>
      <LeafElement1 id="UniqueId9"/>
    </SubElement1>
  </Element2> 
</Root>

2)我的 XPATH 字符串:

//*[@id and contains(@id, "UniqueId8")]/ancestor-or-self::*

3)我想得到这样的结果(从找到的元素到根):

<Root>
  <Element2 id="UniqueId6" AttributeToCheck="true">
    <SubElement1 id="UniqueId7">
      <LeafElement1 id="UniqueId8"/>
    </SubElement1>
  </Element2> 
</Root>

顺便说一句, // [@id and contains(@id, "UniqueId8")]/ancestor-or-self:: /@id 工作正常。

有谁知道如何解决这个问题或只是使用另一个操作而不是祖先或自我?

更新:

我只是执行这个:

DECLARE
  v_xml XMLTYPE;
BEGIN
    SELECT xmltype('<Root>
               <Element1 id="UniqueId1">
            <SubElement1 id="UniqueId2"/>                                           <SubElement2 id="UniqueId3">
                                            <LeafElement1 id="UniqueId4"/>
                                            <LeafElement1 id="UniqueId5"/>
                                        </SubElement2>
                                    </Element1>
                                    <Element2 id="UniqueId6" AttributeToCheck="true">
                                        <SubElement1 id="UniqueId7">
                                            <LeafElement1 id="UniqueId8"/>
                                            <LeafElement1 id="UniqueId9"/>
                                        </SubElement1>
                                    </Element2>
                                </Root>')
    into v_xml
    from dual;

    select extract(v_xml, '//*[@id="UniqueId9"]/ancestor-or-self::*')
    into v_xml
    from dual;

    dbms_output.put_line(v_xml.getStringVal());

END;

但结果我得到了一些奇怪的东西:

<Root>
  <Element1 id="UniqueId1">
              <SubElement1 id="UniqueId2"/>
            <SubElement2 id="UniqueId3">
                                     <LeafElement1 id="UniqueId4"/>
                                                 <LeafElement1 id="UniqueId5"/>
     </SubElement2>
    </Element1>
    <Element2 id="UniqueId6" AttributeToCheck="true">
    <SubElement1 id="UniqueId7">
    <LeafElement1 id="UniqueId8"/>
    <LeafElement1 id="UniqueId9"/>
    </SubElement1></Element2>
</Root>
<Element2 id="UniqueId6" AttributeToCheck="true">
    <SubElement1 id="UniqueId7">
        <LeafElement1 id="UniqueId8"/>
        <LeafElement1 id="UniqueId9"/>
    </SubElement1>
</Element2>

<SubElement1 id="UniqueId7">
    <LeafElement1 id="UniqueId8"/>
    <LeafElement1 id="UniqueId9"/>
</SubElement1>

<LeafElement1 id="UniqueId9"/>
4

4 回答 4

2

XPath 只允许您选择输入文档中的节点,它不允许您更改文档的结构或创建一个新的文档,其中节点正在更改(添加、删除、操作)。因此,一旦您使用路径表达式选择根元素并输出结果,您当然会输出根元素及其包含的所有节点。

所以 XPath 不能做你想做的工作,因为你需要使用 XQuery 或 XSLT;这样,您将能够创建一个新文档,其中包含您不感兴趣的节点被删除。片段输入 xhtml 以分离带有祖先节点的 xhtml 文件 deails是一个示例,其中 XSLT 用于过滤掉那些不是某个节点的祖先或子节点的根元素的后代节点。它比您需要的更多,因为它对多个节点执行此操作并创建多个结果文档,但部分代码正在执行您想要的操作。但是,我不知道您是否可以在 Oracle 的上下文中使用 XSLT 或 XSLT 2.0,所以我不会尝试使该代码适应您的输入示例,除非您明确指出您可以使用 XSLT 以及您可以使用哪个版本的 XSLT在 Oracle 的上下文中使用。

于 2012-11-13T10:15:09.187 回答
2

正如 Martin 所说,您不能使用 XPath 来构造输入中不存在的树。

还有一点:注意 XPath 表达式选择节点。将其视为返回一组指向输入文档中节点的指针。对于运行 XPath 查询的客户端环境来说,通过显示以节点为根的子树来显示这些节点是很常见的。但是 XPath 表达式并没有选择整个树,它只选择了根,节点下方子树的显示可能会让您感到困惑。

于 2012-11-13T10:27:56.513 回答
1

试试这个 XSL 方法:

SQL> with xml as (select xmltype('<Root>
  2    <Element1 id="UniqueId1">
  3      <SubElement1 id="UniqueId2"/>
  4      <SubElement2 id="UniqueId3">
  5        <LeafElement1 id="UniqueId4"/>
  6        <LeafElement1 id="UniqueId5"/>
  7      </SubElement2>
  8    </Element1>
  9    <Element2 id="UniqueId6" AttributeToCheck="true">
 10      <SubElement1 id="UniqueId7">
 11        <LeafElement1 id="UniqueId8"/>
 12        <LeafElement1 id="UniqueId9"/>
 13      </SubElement1>
 14    </Element2>
 15  </Root>') xml from dual),
 16  xsl as (select xmltype('
 17  <xsl:stylesheet version="1.0"
 18   xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 19   <xsl:template match="node()|@*">
 20    <xsl:copy>
 21     <xsl:apply-templates select="*[descendant-or-self::*[contains(@id,''UniqueId8'')]]|@*"/>
 22    </xsl:copy>
 23   </xsl:template>
 24  </xsl:stylesheet>') xsl from dual)
 25  select xm.xml.transform(xs.xsl)
 26    from xml xm, xsl xs;

XM.XML.TRANSFORM(XS.XSL)
--------------------------------------------------------------------------------

<Root>
 <Element2 id="UniqueId6" AttributeToCheck="true">
  <SubElement1 id="UniqueId7">
   <LeafElement1 id="UniqueId8">
   </LeafElement1>
  </SubElement1>
 </Element2>
</Root>
于 2012-11-13T10:52:11.423 回答
0

nick xtender的家伙使用XPATH 找到了很好的解决方案,它确实有效:

   with t_xml as ( select xmltype('
    <Root>
      <Element1 id="UniqueId1">
        <SubElement1 id="UniqueId2"/>
        <SubElement2 id="UniqueId3">
          <LeafElement1 id="UniqueId4"/>
          <LeafElement1 id="UniqueId5"/>
        </SubElement2>
      </Element1>
      <Element2 id="UniqueId6" AttributeToCheck="true">
        <SubElement1 id="UniqueId7">
          <LeafElement1 id2="UniqueId8"/>
          <LeafElement1 id="UniqueId9"/>
        </SubElement1>
      </Element2> 
    </Root>') x from dual)
    select 
       t_xml.*
      ,updatexml(x,'//*[not (descendant-or-self::*[@id2="UniqueId8"])]',chr(10)) upd
    from t_xml
于 2012-11-13T12:41:12.943 回答