XML doc中最近的XPath兄弟,带有结构化标记名称?

时间:2017-01-17 22:36:30

标签: xml xpath

我有什么

一个XML文档,其中节点名称具有严格的命名约定,其中每个节点的级别都反映在其名称中,如下所示:

<root>
    <ABC>
        <ABC_1/>
        <ABC_2>
            <ABC_2_1>
                <ABC_2_1_1/>
            </ABC_2_1>
            <ABC_2_2/>
            <ABC_2_5/>
            <ABC_2_6/>
        </ABC_2>
    </ABC>
    <DEF>
        <DEF_1/>
        <DEF_2/>
        <DEF_59/>
    </DEF>
    ...
</root>

兄弟姐妹的顺序始终保留(如图所示),但并不总是顺序的,即某些节点可能丢失(例如&#34; ABC_2_3&#34;以及&#34; ABC_2_4&#34;上面)。但是, do 存在的节点总是按升序插入。

我想做的事

我有一个简单的XPath用于其中一个缺失的节点,例如: &#34; // ABC_2_4&#34;,如果它不存在,我需要创建/插入具有该名称的新节点。我没有父节点或任何其他信息;我只有那个XPath字符串和XML文档/对象。

所以我所做的就是解析XPath来提取父节点名称(在这个例子中&#34; ABC_2&#34;),然后插入一个新的&#34; ABC_2_4&#34;节点进入该父节点。 (为简单起见,假设父节点将始终存在。)

问题

有没有&#34;技巧&#34;快速找到前一个兄弟,即以某种方式只用一两个查询,而不是从丢失的节点名称向后枚举,并尝试一次选择一个节点,直到找到现有的前一个兄弟?如果我需要插入&#34; DEF_58&#34;节点给出上面的示例XML(即&#34; DEF_2&#34;和#34; DEF_59&#34;),这将是一个非常长/慢的枚举,直到我找到现有的前兄弟(&#34; DEF_2& #34)...

一些笔记(如果可能有帮助):

  1. 此命名约定使所有节点都具有唯一名称(&#34; ABC&#34;,&#34; DEF&#34;等等父级前缀始终是唯一的。)
  2. 深度不会超过上面的示例XML中显示的内容,即&#34; ABC_2_1_1&#34;是最深的&#34;可能的水平。
  3. 谢谢!

1 个答案:

答案 0 :(得分:1)

您可以使用substring-after来获取名称中的最后一个数字,然后找到最后一个数字小于给定数字的节点。您需要使用substring-after次,因为标记名称中有下划线。

//DEF/*[substring-after(name(), '_') < 58][last()]
//ABC_2/*[substring-after(substring-after(name(),'_'), '_') < 4][last()]
//ABC_2_1/*[substring-after(substring-after(substring-after(name(),'_'), '_'), '_') < 44][last()]

这些将分别为DEF_58ABC_2_4ABC_2_44找到前面的兄弟姐妹。