# XML→JSON

XScript предоставляет три способа для преобразования XML-элементов в формат JSON:

1. С помощью XSL-шаблонов. Для этого в элементе `xsl:output` необходимо указать `method="x:json"`.
1. С помощью XSL-функции [x:json-stringify](xslt-functions.md#json-stringify).
1. С помощью XSL-функции [x:js-stringify](xslt-functions.md#js-stringify).

Преобразование XML→JSON обратно симметрично к преобразованию [JSON→XML](json-to-xml.md) и производится в соответствии со следующими правилами.

1. Любой XML-элемент, не содержащий атрибута `type="array"` преобразуется в пару ключ:JSON-объект. Если атрибут name не задан, в качестве ключа используется имя XML-элемента, если задан — значение атрибута name.
1. XML-элемент, содержащий атрибут `type="array"` преобразуется в массив. Непосредственные потомки этого элемента преобразуются в элементы массива. Если же дочерние элементы сами имеют детей, их преобразование осуществляется в соответствии с общими правилами (включая это).
1. Если XML-элемент не содержит атрибута type и содержит дочерние элементы, производится попытка конвертировать его в JSON-объект. Если дочерних элементов нет, значение элемента интерпретируется как строка. Явное указание на строковое значение производится с помощью задания `type="string"`.
1. При конвертировании численных значений (`type="number")`, превышающих максимальное значение для типа Double, число приводится к максимально допустимому для данного типа значению.
1. При конвертировании булевых значений (`type="boolean"`) строка <q>true</q> преобразуется в true, <q>false</q> — в false. Регистр не учитывается. Пустой элемент преобразуется в null.

{% note warning %}

**Преобразование XML-элемента, не содержащего атрибута `type="array"`, может привести потере данных в JSON-выдаче.** Если XML-элемент имеет детей с одинаковым именем, не содержащих атрибута `name`, в JSON-выдачу попадет только последний ребенок.

{% endnote %}

Для предотвращения неоднозначностей при конвертации в JSON рекомендуется указывать тип данных в явном виде с помощью атрибута `type`.

Для предотвращения потери данных в JSON-выдаче, необходимо либо не использовать XML-элементов с одинаковым названием, имеющих общего родителя, либо указывать название свойства с помощью атрибута `name`.

**Пример преобразования XML→JSON**

В данном примере корневой элемент файла `xml_data.xml` преобразуется в JSON с помощью XSL-функции [x:json-stringify](xslt-functions.md#json-stringify).

```xml
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:x="http://www.yandex.ru/xscript"
     version="1.0">
     
<xsl:output method="text" omit-xml-declaration="yes" encoding="utf-8" content-type="application/json; charset=utf-8"/>
     
<xsl:template match="/page">
    <xsl:value-of select="x:json-stringify(.)"/>
</xsl:template>

</xsl:stylesheet>
```

#|
|| xml_data.xml | Результат ||
|| 
```
xml <?xml version="1.0" encoding="UTF-8"?>
 <?xml-stylesheet href="via-function.xsl" type="text/xsl"?>
 <page xmlns:ya="http://ya.ru">
  <element attr="attributes are ignored except of @type and @name">
    <entries>
      <entry>simple entry</entry>
      <entry name="json_name">user defined key</entry>
      <jstring type="string">explicit type defintion</jstring>
      <bool_str type="boolean">no json output</bool_str>
      <bool type="boolean">true</bool>
      <bool_num type="boolean">1</bool_num>
      <bool_void type="boolean"/>
      <list type="array">
       <subentry>first</subentry>
       <subentry>second</subentry>
       <subentry><deep>inside</deep></subentry>
      </list>
      <duplicates>
        <item>First will be lost</item>
        <item>Trust only last</item>
      </duplicates>
      <entry1>987654321012</entry1>
      <entry2 type="number">9876543210123456789</entry2>
    </entries>
    <ya:name>No need to use namespaces</ya:name>
  </element>
  <json type="object">
     <json-object type="json">{"a":123, "c": "str", "b": [1,2,3]}</json-object>
     <json-empty-object type="json"> </json-empty-object>
  </json>
 </page>
 
  ``` 
  | 
  ```javascript
   {"element":{
     "entries":{
         "entry":"simple entry",
         "json_name":"user defined key",
         "jstring":"explicit type defintion",
         "bool":true,
         "bool_void":null,
         "list":["first",
                 "second",
                 {"deep":"inside"}],
         "duplicates":{
             "item":"Trust only last"},
         "entry1":"987654321012",
         "entry2":9.876543210123457e+18},
     "name":"No need to use namespaces"},
     "json":{
         "json-object":{"a":123, "c": "str", "b": [1,2,3]},
         "json-empty-object":null}
 } 
 ```
 ||
 |#

Аналогичный результат можно получить, используя `method="json"` в элементе `xsl:output` XSL-шаблона:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:x="http://www.yandex.ru/xscript"
  version="1.0">
     
<xsl:output method="x:json" encoding="utf-8" omit-xml-declaration="yes" />
  <xsl:template match="/">
    <xsl:copy-of select="."/>
  </xsl:template>
</xsl:stylesheet>
```

