Как заставить xml2js выводить массив для определенных ключей? - PullRequest
0 голосов
/ 18 октября 2019

У меня есть какой-то XML, который я хочу вывести в массив. Но когда существует только один элемент, xml2js выводит один элемент в объект. Когда есть несколько элементов, он выводится как массив. Для согласованности, как заставить его быть массивом?

Мой XML выглядит следующим образом:

const xml = `<Shift>
    <Transaction>
      <Currency>GBP</Currency>
      <Amount>24.50</Amount>
    </Transaction>
</Shift>`

parseStringPromise(xml).then(json => console.log(JSON.stringify(json)))

, который, как вы можете видеть, выводит как:

{
  "Transaction": {
    "Currency": "GBP",
    "Amount": "24.50"
  }
}

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

const xml = `<Shift>
    <Transaction>
      <Currency>GBP</Currency>
      <Amount>24.50</Amount>
    </Transaction>
    <Transaction>
      <Currency>GBP</Currency>
      <Amount>25.50</Amount>
    </Transaction>
    <Transaction>
      <Currency>GBP</Currency>
      <Amount>26.50</Amount>
    </Transaction>
    <Transaction>
      <Currency>GBP</Currency>
      <Amount>27.50</Amount>
    </Transaction>
</Shift>`

parseStringPromise(xml).then(json => console.log(JSON.stringify(json)))

, который выводится в массив, подобный следующему:

{
  "Transaction": [
    {
      "Currency": "GBP",
      "Amount": "24.50"
    },
    {
      "Currency": "GBP",
      "Amount": "25.50"
    },
    {
      "Currency": "GBP",
      "Amount": "26.50"
    },
    {
      "Currency": "GBP",
      "Amount": "27.50"
    }
  ]
}

Как я могу убедиться, что даже при наличии только 1 Transaction элементав XML, что он будет выводить в массив?

Есть ли параметр, который мне нужно передать в мой анализатор или мне нужно переформатировать мой XML?

Ответы [ 2 ]

0 голосов
/ 25 октября 2019

Вы можете использовать camaro для этой цели. camaro позволяет вам написать шаблон на основе xpath, чтобы указать, каким должен быть вывод. в этом случае вы указываете, что хотите получить массив из него

const { transform } = require('camaro')
const xml = `<Shift>
    <Transaction>
      <Currency>GBP</Currency>
      <Amount>24.50</Amount>
    </Transaction>
    <Transaction>
      <Currency>GBP</Currency>
      <Amount>25.50</Amount>
    </Transaction>
    <Transaction>
      <Currency>GBP</Currency>
      <Amount>26.50</Amount>
    </Transaction>
    <Transaction>
      <Currency>GBP</Currency>
      <Amount>27.50</Amount>
    </Transaction>
</Shift>`

;(async function () {
    const template = {
        transactions: ['/Shift/Transaction', {
            Currency: 'Currency',
            Amount: 'Amount'
        }]
    }

    console.log(await transform(xml, template));

})()

output

{ transactions:
   [ { Currency: 'GBP', Amount: '24.50' },
     { Currency: 'GBP', Amount: '25.50' },
     { Currency: 'GBP', Amount: '26.50' },
     { Currency: 'GBP', Amount: '27.50' } ] }

, даже когда есть только 1 элемент

const { transform } = require('../')
const xml = `<Shift>
    <Transaction>
      <Currency>GBP</Currency>
      <Amount>24.50</Amount>
    </Transaction>
</Shift>`

;(async function () {
    const template = {
        transactions: ['/Shift/Transaction', {
            Currency: 'Currency',
            Amount: 'Amount'
        }]
    }

    console.log(await transform(xml, template));

})()

output

{ transactions: [ { Currency: 'GBP', Amount: '24.50' } ] }
0 голосов
/ 18 октября 2019

Существует множество конвертеров XML в JSON, и все они имеют такую ​​проблему. Они делают то, что вы хотите в некоторых случаях, а не в других, и ни один из них не дает большого контроля. Если вы хотите контролировать создаваемый JSON, я бы порекомендовал использовать XSLT 3.0: это позволяет преобразовать XML в соответствии со структурой JSON, который вы хотите сгенерировать, перед вызовом xml-to-json() для выполнения преобразования.

...