如何合并元素并将它们分组

How to merge elements and group them

如何合并以下 XML 片段:

片段 1:

    <drug>
        <title>Paracetamol</title>
        <indications outputclass="indicationsAndDose">
            <title>Indications and dose</title>
            <body>
                <section outputclass="indicationAndDoseGroup">
                    <sectiondiv outputclass="therapeuticIndications">
                        <p outputclass="therapeuticIndication">Some indication 1</p>
                        <p outputclass="therapeuticIndication">Some indication 2</p>
                    </sectiondiv>
                </section>
            </body>
        </indications>
    </drug>

片段 2:

    <drug>
        <title>Abacavir</title>
        <indications outputclass="indicationsAndDose">
            <title>Indications and dose</title>
            <body>
                <section outputclass="indicationAndDoseGroup">
                    <sectiondiv outputclass="therapeuticIndications">
                        <p outputclass="therapeuticIndication">Some indication 2</p>
                    </sectiondiv>
                </section>
            </body>
        </indications>
    </drug>

接受标准:

我需要输出一个 XML 片段,它是片段 1 和片段 2 的超集,但需要根据元素、属性和值以不同的方式完成。

  1. 当元素相同但值不同并且它们没有属性时,它们应该被合并,例如"Paracetamol" 和 "Abacavir"
  2. 当元素具有相同的属性时,它们应该是合并值,例如"Some indication 1"
  3. 解决方案应该是动态的,因为上述规则可以应用于任何类型的元素,即 <title> <section> <p>

    <drug>
        <title>Paracetamol</title>
        <indications outputclass="indicationsAndDose">
            <title>Indications and dose</title>
            <body>
                <section outputclass="indicationAndDoseGroup">
                    <sectiondiv outputclass="therapeuticIndications">
                        <p outputclass="therapeuticIndication">Some indication 1</p>
                        <p outputclass="therapeuticIndication">Some indication 2</p>
                    </sectiondiv>
                </section>
            </body>
        </indications>
    </drug>
    

我不确定这是否是您想要的那种合并,因为您的要求很模糊!但是,它会根据您提供的输入生成输出:

declare variable $local:xml1 := document {
    <drug>
        <title>Paracetamol</title>
        <indications outputclass="indicationsAndDose">
            <title>Indications and dose</title>
            <body>
                <section outputclass="indicationAndDoseGroup">
                    <sectiondiv outputclass="therapeuticIndications">
                        <p outputclass="therapeuticIndication">Some indication 1</p>
                    </sectiondiv>
                </section>
            </body>
        </indications>
    </drug>
};
declare variable $local:xml2 := document {
    <drug>
        <title>Abacavir</title>
        <indications outputclass="indicationsAndDose">
            <title>Indications and dose</title>
            <body>
                <section outputclass="indicationAndDoseGroup">
                    <sectiondiv outputclass="therapeuticIndications">
                        <p outputclass="therapeuticIndication">Some indication 2</p>
                    </sectiondiv>
                </section>
            </body>
        </indications>
    </drug>
};

declare function local:merge($i1, $i2) {
    if (node-name($i1) eq node-name($i2)) then
        (
            (: When elements are the same and the value is different
               and they have no attributes they should be merged 
               e.g. "Paracetamol" and "Abacavir"
            :)
            if (empty(($i1/@*, $i2/@*))) then
                element {node-name($i1)} {
                    $i1/@*,
                    $i1/text(),
                    let $ii1 := $i1/node()[1]
                    let $ii2 := $i2/node()[1]
                    return
                        if (not(empty($ii1)) and not(empty($ii2))) then
                            local:merge($ii1, $ii2)
                        else()
                }

            (: When the elements have the same attribute then they
               should be merged value e.g. "Some indication 1"
            :)
            else if (fn:deep-equal($i1/@*, $i2/@*)) then
                (
                    element {node-name($i1)} {
                        $i1/@*,
                        $i1/text(),
                        let $ii1 := $i1/node()[1]
                        let $ii2 := $i2/node()[1]
                        return
                            if (not(empty($ii1)) and not(empty($ii2))) then
                                local:merge($ii1, $ii2)
                            else()
                    },
                    if (not(empty($i1/text())) and not(empty($i2/text()))) then
                        element {node-name($i2)} {
                            $i2/@*,
                            $i2/text()
                        }
                    else()
                )
            else (),
            let $ii1 := $i1/following-sibling::node()[1]
            let $ii2 := $i2/following-sibling::node()[1]
            return
                if (not(empty($ii1)) and not(empty($ii2))) then
                    local:merge($ii1, $ii2)
                else()
        )
    else()
};

local:merge($local:xml1/drug, $local:xml2/drug)