Как вывести некоторые необязательные элементы/узлы XML, всегда используя XQUERY

У меня есть требование, когда мне нужно всегда выводить необязательные элементы XML (независимо от доступности данных) при записи в файл .csv.

XML-формат файла

<entries> 
  <countryCode>123</countryCode>  
  <adminDataMap> 
    <testAccount>True</testAccount>  
    <code>11</code> 
  </adminDataMap>  
  <privateMap> 
    <email>[email protected]</email>  
    <cancelReason>Not interested</cancelReason> 
  </privateMap> 
</entries>

Здесь «записи» Корневой элемент «cancelReason», «testAccount» являются необязательными элементами, которые будут доступны только после того, как будут получены данные.

т. е. некоторые записи будут иметь эти «необязательные» поля, а другие — нет.

Я написал XQuery для извлечения всех этих элементов.

let $entries := /root/entries
return
    for $entry in $entries
    return
    <entries>
    {
        $entry/*,
        $entry/privateMap/email,
        $entry/privateMap/cancelReason,
        $entry/adminDataMap/code,
        $entry/adminDataMap/testAccount
    }
    </entries>

Мое требование состоит в том, чтобы извлечь все обязательные и необязательные элементы как ВЫВОД. т. е. Выходные метаданные всегда остаются неизменными. Если необязательный 'cancelReason' не имеет значения, он будет заполнен пробелами/нулями [что-то вроде этого]

Пожалуйста, сообщите какие-либо опции в XQUERY, которые можно написать для достижения этой цели.


person Tom George    schedule 29.06.2016    source источник


Ответы (2)


Попробуйте этот XQuery:

let $entries := $root/entries

for $entry in $entries

return <OUTPUT>
{<mandatory>{$entry//countryCode}
{<adminDataMap>{$entry//adminDataMap/code}</adminDataMap>}
{$entry//privateMap/email}</mandatory>}
{<optional>{<testAccount>{data($entry/adminDataMap/testAccount)}</testAccount>}
<cancelReason>{data($entry/privateMap/cancelReason)}</cancelReason></optional>
}</OUTPUT>

что дает вам обязательные и необязательные элементы отдельно для каждой записи.

person Vinod    schedule 29.06.2016

Попробуйте этот XQuery:

for $entry in $entries
return
    <entries>
    {
        for $admin in $entry/adminDataMap
        return
            <admin>
                {$admin/code}
                <testAccount>{data($admin/testAccount)}</testAccount>
            </admin>,

        for $private in $entry/privateMap
        return
            <private>
                {$private/email}
                <cancelReason>{data($private/cancelReason)}</cancelReason>
            </private>
    }
    </entries>

Это даст вам пустые элементы для отсутствующих необязательных элементов.


Ну попробуй это

return
    <entries>
    {
        for $admin in $entries/adminDataMap
        return
            <admin>
                {$admin/code}
                <testAccount>{data($admin/testAccount)}</testAccount>
            </admin>,

        for $private in $entries/privateMap
        return
            <private>
                {$private/email}
                <cancelReason>{data($private/cancelReason)}</cancelReason>
            </private>
    }
    </entries>

Я проверил оба метода на BaseX и SqlServer - оба работают.


Я думаю, все зависит от того, как вы установите начальное значение.
Я вижу root в вашем коде:

let $entries := /root/entries

При этом в xml нет элемента с именем root.

Этот код работает, если значение установлено следующим образом:

let $entries :=
<entries>
    <!-- ... -->
</entries>
person Alexander Petrov    schedule 29.06.2016
comment
Я попробовал ваш подход. Я видел, что когда я выполняю все три цикла FOR (с переменными 'entry', 'admin', 'private'), выводятся только элементы/поля, определенные с помощью цикла 'entry'. другие 2 цикла FOR 'admin', 'private' игнорируются. Однако, когда я пробовал циклы «admin», «private» FOR отдельно, он работал как шарм. Может быть, я ошибаюсь в синтаксисе. Не уверен. Пожалуйста, порекомендуйте. - person Tom George; 01.07.2016