Как объединить элементы и сгруппировать их - PullRequest
0 голосов
/ 07 марта 2020

Как объединить следующие 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. Когда элементы одинаковы, а значения разные и у них нет атрибутов, их следует объединить, например, «Парацетамол» и «Абакавир»
  2. Когда элементы имеют один и тот же атрибут, тогда они должны быть объединены в значение, например «Некоторая индикация 1»
  3. Решение должно быть динамическим c в том смысле, что вышеуказанные правила могут быть применены к любому типу элемента, т.е. <title> <section> <p> et c

    <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>
    

1 Ответ

1 голос
/ 07 марта 2020

Я не уверен, что вы хотите такого слияния, потому что ваши требования довольно расплывчаты! Тем не менее, он производит вывод из введенного вами ввода:

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)
...