Отфильтровать узлы из XML полезной нагрузки - PullRequest
0 голосов
/ 09 января 2020

Использование: Mule 3.9, Dataweave 1.0

Я пытаюсь отфильтровать нежелательные узлы в документе XML по значению дочернего поля (TestData.Orders.Items.ItemCategory).

В моем примере есть 3 элемента, мне нужно удалить элементы, которые не содержат значение 'CAT1' в поле ItemCategory. То же самое относится и к документам, но это должно быть то же решение.

<TestData>
    <Orders uniqueId="6000:1234">
        <CoverPage>
            <Number>CPN-0001</Number>
        </CoverPage>
        <Items referentId="9000:100:10">
            <ItemNumber>AAA-0001</ItemNumber>
            <ItemCategory>CAT2|CAT3</ItemCategory>
            <Description>Just another description</ODescription>
        </Items>
        <Items referentId="9000:200:20">
            <ItemNumber>AAA-0002</ItemNumber>
            <ItemCategory>CAT2|CAT1|CAT3</ItemCategory>
            <OldItemDescription>Just another description</OldItemDescription>
        </Items>
        <Items referentId="9000:300:30">
            <ItemNumber>AAA-0003</ItemNumber>
            <ItemCategory>CAT2|CAT3</ItemCategory>
            <OldItemDescription>Just another description</OldItemDescription>
        </Items>
        <Page2/>
    </Orders>

    <Documents uniqueId="9000:100:10">
        <Title>
            <Number>AAA-0001</Number>
            <DocumentCategory>CAT2|CAT3</DocumentCategory>
        </Title>
        <ChangeHistory>
            <RelDate>2019-12-10T01:29:28Z</RelDate>
            <Number>CHN-0001</Number>
        </ChangeHistory>
    </Documents>
    <Documents uniqueId="9000:100:20">
        <Title>
            <Number>AAA-0002</Number>
            <DocumentCategory>CAT2|CAT1|CAT3</DocumentCategory>
        </Title>
        <ChangeHistory>
            <RelDate>2019-12-10T01:29:28Z</RelDate>
            <Number>CHN-0001</Number>
        </ChangeHistory>
    </Documents>
    <Documents uniqueId="9000:100:30">
        <Title>
            <Number>AAA-0003</Number>
            <DocumentCategory>CAT2|CAT3</DocumentCategory>
        </Title>
        <ChangeHistory>
            <RelDate>2019-12-10T01:29:28Z</RelDate>
            <Number>CHN-0001</Number>
        </ChangeHistory>
    </Documents>
</TestData>

Поэтому мне нужно преобразовать приведенный выше пример в приведенный ниже пример, сохранив только те элементы и документы, которые содержат значение 'CAT1 'в поле ItemCategory.

<TestData>
    <Orders uniqueId="6000:1234">
        <CoverPage>
            <Number>CPN-0001</Number>
        </CoverPage>
        <Items referentId="9000:200:20">
            <ItemNumber>AAA-0002</ItemNumber>
            <ItemCategory>CAT2|CAT1|CAT3</ItemCategory>
            <OldItemDescription>Just another description</OldItemDescription>
        </Items>
        <Page2/>
    </Orders>

    <Documents uniqueId="9000:100:20">
        <Title>
            <Number>AAA-0002</Number>
            <DocumentCategory>CAT2|CAT1|CAT3</DocumentCategory>
        </Title>
        <ChangeHistory>
            <RelDate>2019-12-10T01:29:28Z</RelDate>
            <Number>CHN-0001</Number>
        </ChangeHistory>
    </Documents>
</TestData>

Стратегия фильтрации и перестроения:

Я попробовал подход, в котором я создал 2 функции фильтра (одну для элементов и 1 для документов). ) и затем пересоберите документ с нуля,

Filter:

%function cleanItems(items) items filter ((lower $.ItemCategory contains 'cat1') == true)
%function cleanDocuments(docs) docs filter ((lower $.ns0#Title.DocumentCategory contains 'cat1') == true)

Перестройте с нуля:

{
    TestData @(xmlns: "http://www.oracle.com/webfolder/technetwork/xml/plm/2014/08/"): {
        ChangeOrders @(uniqueId: payload.ns0#TestData.ns0#Orders.@uniqueId): {
        }
        ++ payload.ns0#TestData.*ns0#Orders.ns0#CoverPage
        ++ cleanItems(payload.ns0#TestData.*ns0#Orders.*ns0#Items)
        ++ payload.ns0#TestData.*ns0#Orders.ns0#PageTwo
    } 
    ++ cleanDocuments(payload.ns0#TestData.*ns0#Documents)
}

В принципе, это работает, но я теряю атрибуты узла ' xmlns 'и' xmlns: xsd 'и' xmlns: xsi 'и' xsi: schemaLocation '.

Затем я попытался вставить пропущенные атрибуты (https://docs.mulesoft.com/mule-runtime/4.2/dataweave-cookbook-insert-attribute) при этом @ (xmlns: "http://www.oracle.com/webfolder/technetwork/xml/plm/2014/08/"), но если в атрибуте содержится двоеточие ':', оно завершается неудачно, и я не знаю, как избежать двоеточия. Другая проблема, возникающая при его создании с нуля, заключается в том, что я могу вставлять только те узлы, о которых я знаю (для документа нет XSD).

Поскольку функциональность, которую я пытаюсь реализовать, является частью гораздо большего потока Мне нужно оставить полезную нагрузку XML на 100% одинаковой (но без нежелательных узлов), иначе это вызовет проблемы.

Так что я думаю о подходе, при котором нежелательные узлы можно просто удалить из документ, так что мне не нужно перестраивать его с нуля.

Надеюсь, вы поможете, я перепробовал все, что мог придумать.

1 Ответ

0 голосов
/ 10 января 2020

Попробуйте, если пространства имен являются частью входных данных, они должны быть сохранены в выходных данных. Я мог бы сделать это немного проще, но уже поздно, и я безумный банкомат.

%dw 1.0
%output application/xml

%var testKey = (k,v) ->     k as :string match {
    "Items"     -> ($ != "Items" or ($ == "Items" and (v.ItemCategory contains "CAT1"))),
    "Documents" -> ($ != "Documents" or ($ == "Documents" and (v.Title.DocumentCategory contains "CAT1"))) ,
    default     -> true
}

%var traverse = (ds) -> ds match {
    :object -> $ mapObject ( (v,k) -> (
        {((k): traverse(v)) when testKey(k,v)}
    ) ),
    default -> $
}
---
traverse(payload)
...