0

I have the two following XMLs and the problem statement is as follows.

  1. Parse XML 1 and if subnode of any node_x contains 'a' in its name (like in value_a_0) and value_a_0 contains a specific number, parse XML 2 and go to node_x-1 for all abc_x in and compare the content of value_x-1_0/1/2/3 with certain entities.

  2. If subnode of any node_x contains 'b' in its name (like in value_b_0) and value_b_0 contains a specific number(say 'm'), parse XML 2 and go to node_x+1 for all abc_x in and compare the content of value_x-1_0/1/2/3 with 'm'.

Example : For all the value_a_0 in record1 check if value_a_0 node contains 5. If so, which are the case for node_1 and node_9, go to record2/node_0 and record2/node_8 and compare the contents of value_0_0/1/2/3 whether they contains 5 or not. Similarly, for rest of the cases.

I was wondering what would be the best practice to solve it? Is there any hash-table approach in Xpath 3.0?

First XML

<record1>
    <node_1>
        <value_a_0>5</value_1_0>
        <value_b_1>0</value_1_1>
        <value_c_2>10</value_1_2>
        <value_d_3>8</value_1_3>
    </node_1>
   .................................
   .................................

    <node_9>
        <value_a_0>5</value_a_0>
        <value_b_1>99</value_b_1>
        <value_c_2>53</value_c_2>
        <value_d_3>5</value_d_3>
  </node_9>
</record1>

Second XML

<record2>
  <abc_0>
        <node_0>
            <value_0_0>5</value_0_0>
            <value_0_1>0</value_0_1>
            <value_0_2>150</value_0_2>
            <value_0_3>81</value_0_3>
        </node_0>
        <node_1>
            <value_1_0>55</value_1_0>
            <value_1_1>30</value_1_1>
            <value_1_2>150</value_1_2>
            <value_1_3>81</value_1_3>
        </node_1>
       .................................
       .................................

        <node_63>
            <value_63_0>1</value_63_0>
            <value_63_1>99</value_63_1>
            <value_63_2>53</value_63_2>
            <value_63_3>5</value_63_3>
      </node_63>
   </abc_0>
   ================================================
   <abc_99>
        <node_0>
            <value_0_0>555</value_0_0>
            <value_0_1>1810</value_0_1>
            <value_0_2>140</value_0_2>
            <value_0_3>80</value_0_3>
        </node_0>            
        <node_1>
            <value_1_0>555</value_1_0>
            <value_1_1>1810</value_1_1>
            <value_1_2>140</value_1_2>
            <value_1_3>80</value_1_3>
        </node_1>
        <node_2>
            <value_2_0>5</value_2_0>
            <value_2_1>60</value_2_1>
            <value_2_2>10</value_2_2>
            <value_2_3>83</value_2_3>
        </node_2>
       .................................
       .................................

        <node_63>
            <value_63_0>1</value_63_0>
            <value_63_1>49</value_63_1>
            <value_63_2>23</value_63_2>
            <value_63_3>35</value_63_3>
       </node_63>
    </abc_99>
  </record2>
4

2 回答 2

4

首先,我要说使用这样的结构化元素名称是非常糟糕的 XML 设计。这是相关的,因为当您在 XPath 或 XQuery 中执行连接查询时,您非常依赖优化器来找到快速执行路径(例如哈希连接),并且您的查询越“奇怪”,优化器就越不可能找到一个快速的执行策略。

我经常从将“奇怪”的 XML 转换为更卫生的东西开始。例如,在这种情况下,我将转换<value_a_0>5</value_1_0><value cat="a" seq="0">5</value>. 这使得编写查询更容易,优化器更容易识别它,并且转换阶段是可重用的,因此您可以在对 XML 的任何操作之前应用它,而不仅仅是这个。

如果您正在寻找比 O(n*m) 更好的连接查询性能,您需要查看您选择的 XPath 引擎的功能。例如,Saxon-EE 将进行此类优化,Saxon-HE 不会。与 XPath 引擎相比,您通常更可能在 XQuery 引擎中找到高级优化。

至于您查询的细节,当您开始谈论abc_x. 我不确定那指的是什么。

于 2019-08-11T07:35:17.723 回答
2

这似乎是一项可以通过分组部分解决的任务,但正如在您之前的示例中一样,XML 元素名称的不良使用都因索引值而异,这些索引值应该是元素或属性值的一部分,而不是元素名称的一部分,这使得它更难编写简洁的代码:

let $abc-elements := $doc2/record2/*
for $node-element in record1/*
for $index in (1 to count($node-element[1]/*))
for $index-element in $node-element/*[position() = $index]
group by $index, $group-value := $index-element
where tail($index-element)
return 
    <group index="{$index}" value="{$group-value}">
    {
        let $suffixes := $index-element/../string((xs:integer(substring-after(local-name(), '_')) - 1)),
            $relevant-abc-node-elements := $abc-elements/*[substring-after(local-name(), '_') = $suffixes]
        return $relevant-abc-node-elements[* = $group-value]
    }
    </group>

https://xqueryfiddle.liberty-development.net/nbUY4kA

于 2019-08-11T09:42:19.650 回答