根据XPath中的值遍历多个祖先的子节点的链接列表

时间:2018-04-27 00:32:15

标签: xml xslt-2.0 xpath-2.0

我们的一家供应商将他们的信息存储在几乎链接列表样式的XML代码中。我一直难以想出一种遍历和连接所有数据的方法。以下是XML代码:

<bibliographic-data>
  <reference>
     <document-id>
       <doc-number>15492293</doc-number>
     </document-id>
  </reference>
</bibliographic-data>


    <related-documents>
            <divider>
                <relation>
                    <parent-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>09861196</doc-number>
                            <date>20010518</date>
                        </document-id>
                        <parent-document>
                            <document-id>
                                <code>UC</code>
                                <doc-number>6514193</doc-number>
                                <date>20030204</date>
                            </document-id>
                        </parent-document>
                    </parent-doc>
                    <child-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>10665793</doc-number>
                        </document-id>
                    </child-doc>
                </relation>
            </divider>      
            <paperback>
                <relation>
                    <parent-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>14711658</doc-number>
                            <date>20150513</date>
                        </document-id>
                        <parent-status>SHELVED</parent-status>
                    </parent-doc>
                    <child-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>15492293</doc-number>
                        </document-id>
                    </child-doc>
                </relation>
            </paperback>
            <paperback>
                <relation>
                    <parent-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>14473159</doc-number>
                            <date>20140829</date>
                        </document-id>
                        <parent-document>
                            <document-id>
                                <code>UC</code>
                                <doc-number>9636401</doc-number>
                                <date>20170502</date>
                            </document-id>
                        </parent-document>
                    </parent-doc>
                    <child-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>14711658</doc-number>
                        </document-id>
                    </child-doc>
                </relation>
            </paperback>

            <paperback>
                <relation>
                    <parent-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>12823700</doc-number>
                            <date>20100625</date>
                        </document-id>
                        <parent-document>
                            <document-id>
                                <code>UC</code>
                                <doc-number>8470294</doc-number>
                                <date>20130625</date>
                            </document-id>
                        </parent-document>
                    </parent-doc>
                    <child-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>13911616</doc-number>
                        </document-id>
                    </child-doc>
                </relation>
            </paperback>
            <paperback>
                <relation>
                    <parent-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>10665793</doc-number>
                            <date>20030919</date>
                        </document-id>
                        <parent-document>
                            <document-id>
                                <code>UC</code>
                                <doc-number>7776310</doc-number>
                                <date>20100817</date>
                            </document-id>
                        </parent-document>
                    </parent-doc>
                    <child-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>12823700</doc-number>
                        </document-id>
                    </child-doc>
                </relation>
            </paperback>
            <hardcover>
                <relation>
                    <parent-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>13911616</doc-number>
                            <date>20130613</date>
                        </document-id>
                        <parent-document>
                            <document-id>
                                <code>UC</code>
                                <doc-number>8821835</doc-number>
                                <date>20140902</date>
                            </document-id>
                        </parent-document>
                    </parent-doc>
                    <child-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>14473159</doc-number>
                        </document-id>
                    </child-doc>
                </relation>
            </hardcover>
            <hardcover>
                <relation>
                    <parent-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>09861326</doc-number>
                            <date>20010518</date>
                        </document-id>
                        <parent-document>
                            <document-id>
                                <code>UC</code>
                                <doc-number>6746661</doc-number>
                                <date>20040608</date>
                            </document-id>
                        </parent-document>
                    </parent-doc>
                    <child-doc>
                        <document-id>
                            <code>UC</code>
                            <doc-number>09861196</doc-number>
                        </document-id>
                    </child-doc>
                </relation>
            </hardcover>
        </related-documents>

我正在尝试使用子级和父级doc-number字段遍历所有节点。它应该连接15492293应该启动链后跟14711658 - &gt; 14473159 - &gt; 13911616 - &gt; 12823700 - &gt; 10665793 - &gt; 09861196 - &gt; 09861326

我试图使用以下XPAth表达式: for $ i in(./divider,。/ paperback,。/ drcover)
[relation / child-doc / document-id / doc-number = / bibliographic-data / reference / document-id / doc-number] 返回 $ $ f $ 返回 $ f [relation / child-doc / document-id / doc-number = $ i / relation / parent-doc / document-id / doc-number]

遍历多个祖先几乎链接列表样式的节点的优雅方式是什么。任何帮助都会有所帮助。我可以根据要求提供进一步的解释。

1 个答案:

答案 0 :(得分:0)

我认为您可以在引用后编写递归函数,最好使用密钥完成:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="xs mf"
    version="3.0">

    <xsl:param name="start-id">15492293</xsl:param>

    <xsl:output method="text"/>

    <xsl:key name="parent" match="related-documents/*" use="relation/child-doc/document-id/doc-number"/>

    <xsl:function name="mf:get-ancestor-ids" as="xs:integer*">
        <xsl:param name="item" as="element()"/>
        <xsl:sequence 
            select="let $parent-id := $item/relation/parent-doc/document-id/doc-number,
                        $parent := key('parent', $parent-id, root($item)) 
                        return (xs:integer($parent-id), $parent!mf:get-ancestor-ids(.))"/>
    </xsl:function>

    <xsl:template match="/" name="xsl:initial-template">
        <xsl:value-of select="$start-id, mf:get-ancestor-ids(key('parent', $start-id))" separator=" -> "/>
    </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/eiZQaF1给出了结果

15492293 -> 14711658 -> 14473159 -> 13911616 -> 12823700 -> 10665793 -> 9861196 -> 9861326

该示例使用了一些XSLT和XPath 3功能,例如let!,但您当然可以使用xsl:variable而不是let为XSLT和XPath 2.0重写该功能$parent/mf:get-ancestor-ids(.)的{​​{1}}或if ($parent) then mf:get-ancestor-ids($parent) else ()

$parent!mf:get-ancestor-ids(.)

http://xsltransform.net/93nvfd2