Вы просматриваете документацию Apigee Edge .
Перейдите к документации Apigee X. информация
Что
Эта политика преобразует сообщения из формата расширяемого языка разметки (XML) в нотацию объектов JavaScript (JSON), предоставляя вам несколько вариантов управления преобразованием сообщений.
Предполагая, что целью является преобразование ответа в формате XML в ответ в формате JSON, политика будет прикреплена к потоку ответа (например, Response/ProxyEndpoint/PostFlow).
О
В типичном сценарии посредничества политика преобразования JSON в XML в потоке входящих запросов часто сочетается с политикой преобразования XML в JSON в потоке исходящих ответов. Объединив политики таким образом, можно предоставить JSON API для серверных служб, которые изначально поддерживают только XML.
В сценариях, где API используются различными клиентскими приложениями, которым может потребоваться либо JSON, либо XML, формат ответа можно задать динамически, настроив политики JSON в XML и XML в JSON для условного выполнения. См. раздел «Переменные потока и условия» для реализации этого сценария.
Образцы
Подробное обсуждение преобразования JSON и XML см. в http://community.apigee.com/articles/1839/converting-between-xml-and-json-what-you-need-to-k.html .
Преобразование ответа
<XMLToJSON name="ConvertToJSON"> <Options> </Options> <OutputVariable>response</OutputVariable> <Source>response</Source> </XMLToJSON>
Эта конфигурация — минимальная конфигурация, необходимая для преобразования XML в JSON — принимает ответное сообщение в формате XML в качестве источника, а затем создает сообщение в формате JSON, которое заполняется в выходной переменной response . Edge автоматически использует содержимое этой переменной в качестве сообщения для следующего шага обработки.
Ссылка на элемент
Ниже приведены элементы и атрибуты, которые вы можете настроить в этой политике.
<XMLToJSON async="false" continueOnError="false" enabled="true" name="XML-to-JSON-1"> <DisplayName>XML to JSON 1</DisplayName> <Source>response</Source> <OutputVariable>response</OutputVariable> <Options> <RecognizeNumber>true</RecognizeNumber> <RecognizeBoolean>true</RecognizeBoolean> <RecognizeNull>true</RecognizeNull> <NullValue>NULL</NullValue> <NamespaceBlockName>#namespaces</NamespaceBlockName> <DefaultNamespaceNodeName>&</DefaultNamespaceNodeName> <NamespaceSeparator>***</NamespaceSeparator> <TextAlwaysAsProperty>true</TextAlwaysAsProperty> <TextNodeName>TEXT</TextNodeName> <AttributeBlockName>FOO_BLOCK</AttributeBlockName> <AttributePrefix>BAR_</AttributePrefix> <OutputPrefix>PREFIX_</OutputPrefix> <OutputSuffix>_SUFFIX</OutputSuffix> <StripLevels>2</StripLevels> <TreatAsArray> <Path unwrap="true">teachers/teacher/studentnames/name</Path> </TreatAsArray> </Options> <!-- Use Options or Format, not both --> <Format>yahoo</Format> </XMLToJSON>
Атрибуты <XMLtoJSON>
<XMLtoJSON async="false" continueOnError="false" enabled="true" name="XML-to-JSON-1">
В следующей таблице описаны атрибуты, общие для всех родительских элементов политики:
| Атрибут | Описание | По умолчанию | Присутствие |
|---|---|---|---|
name | Внутреннее имя политики. Значение атрибута При необходимости используйте элемент | Н/Д | Необходимый |
continueOnError | Установите значение Установите значение | ЛОЖЬ | Необязательный |
enabled | Установите значение Установите значение | истинный | Необязательный |
async | Этот атрибут устарел. | ЛОЖЬ | Устарело |
Элемент <DisplayName>
Используйте в дополнение к атрибуту name , чтобы пометить политику в редакторе прокси-сервера пользовательского интерфейса управления другим именем на естественном языке.
<DisplayName>Policy Display Name</DisplayName>
| По умолчанию | Н/Д Если вы опустите этот элемент, будет использовано значение атрибута |
|---|---|
| Присутствие | Необязательный |
| Тип | Нить |
Элемент <Источник>
Переменная, запрос или ответ, содержащая XML-сообщение, которое вы хотите преобразовать в JSON.
Заголовок HTTP Content-type исходного сообщения должен иметь значение application/xml , иначе политика не будет применена.
Если <Source> не определен, то он рассматривается как сообщение (которое разрешается как запрос, когда политика прикрепляется к потоку запросов, или как ответ, когда политика присоединяется к потоку ответов).
Если исходную переменную невозможно разрешить или она преобразуется в тип, не являющийся сообщением, политика выдает ошибку.
<Source>response</Source>
| По умолчанию | запрос или ответ, в зависимости от того, где политика добавляется в поток прокси-сервера API. |
| Присутствие | Необязательный |
| Тип | сообщение |
Элемент <OutputVariable>
Сохраняет выходные данные преобразования формата XML в JSON. Обычно это то же значение, что и в источнике, то есть обычно ответ XML преобразуется в ответ JSON.
Полезная нагрузка XML-сообщения анализируется и преобразуется в JSON, а для заголовка HTTP Content-type сообщения в формате XML устанавливается значение application/json .
Если OutputVariable не указан, source рассматривается как OutputVariable . Например, если source является response , то OutputVariable по умолчанию имеет значение response .
<OutputVariable>response</OutputVariable>
| По умолчанию | запрос или ответ, в зависимости от того, где политика добавляется в поток прокси-сервера API. |
| Присутствие | Этот элемент является обязательным, если переменная, определенная в элементе <Source> , имеет строковый тип. |
| Тип | сообщение |
<Опции>
Опции дают вам контроль над преобразованием XML в JSON. Используйте либо группу <Options> , которая позволяет добавлять определенные параметры преобразования, либо элемент <Format> , который позволяет ссылаться на шаблон предопределенных параметров. Вы не можете использовать одновременно <Options> и <Format> .
<Options> требуется, если <Format> не используется.
Элемент <Options>/<RecounceNumber>
Если это правда, то числовые поля в полезных данных XML сохраняют свой исходный формат.
<RecognizeNumber>true</RecognizeNumber>
Рассмотрим следующий пример XML:
<a> <b>100</b> <c>value</c> </a>
Если true , преобразуется в:
{
"a": {
"b": 100,
"c": "value"
}
} Если false , преобразуется в:
{
"a": {
"b": "100",
"c": "value"
}
}| По умолчанию | ЛОЖЬ |
| Присутствие | Необязательный |
| Тип | логическое значение |
Элемент <Options>/<RecknoweBoolean>
Позволяет преобразованию сохранять логические значения true/false вместо преобразования значений в строки.
<RecognizeBoolean>true</RecognizeBoolean>
Для следующего примера XML:
<a> <b>true</b> <c>value</c> </a>
Если true , преобразуется в:
{
"a": {
"b": true,
"c": "value"
}
}Если false , преобразуется в:
{
"a": {
"b": "true",
"c": "value"
}
}| По умолчанию | ЛОЖЬ |
| Присутствие | Необязательный |
| Тип | логическое значение |
Элемент <Options>/<RecounceNull>
Позволяет конвертировать пустые значения в нулевые значения.
<RecognizeNull>true</RecognizeNull>
Для следующего XML:
<a> <b></b> <c>value</c> </a>
Если true , преобразуется в:
{
"a": {
"b": null,
"c": "value"
}
}Если false , преобразуется в:
{
"a": {
"b": {},
"c": "value"
}
}| По умолчанию | ЛОЖЬ |
| Присутствие | Необязательный |
| Тип | логическое значение |
Элемент <Options>/<NullValue>
Указывает значение, в которое следует преобразовать распознанные нулевые значения в исходном сообщении. По умолчанию значение равно null . Этот параметр эффективен только в том случае, если RecognizeNull имеет значение true.
<NullValue>not-present</NullValue>
| По умолчанию | null |
| Присутствие | Необязательный |
| Тип | Нить |
<Параметры>/<ИмяПространстваИменБлока>
<Параметры>/<имя_пространства_узла_по умолчанию>
Элементы <Options>/<NamespaceSeparator>
Используйте эти элементы вместе.
<NamespaceBlockName>#namespaces</NamespaceBlockName> <DefaultNamespaceNodeName>&</DefaultNamespaceNodeName> <NamespaceSeparator>***</NamespaceSeparator>
Рассмотрим следующий пример XML:
<a xmlns="http://ns.com" xmlns:ns1="http://ns1.com"> <ns1:b>value</ns1:b> </a>
Если NamespaceSeparator не указан, создается следующая структура JSON:
{
"a": {
"b": "value"
}
}Если элементы NamespaceBlockName , DefaultNamespaceNodeName и NamespaceSeparator указаны как #namespaces , & и *** соответственно, то генерируется следующая структура JSON:
{
"a": {
"#namespaces": {
"&": "http://ns.com",
"ns1": "http://ns1.com"
},
"ns1***b": "value"
}
}| По умолчанию | См. примеры выше. |
| Присутствие | Необязательный Однако если вы укажете <NamespaceBlockName> , вы также должны указать два других элемента. |
| Тип | Струны |
<Параметры>/<TextAlwaysAsProperty>
Элементы <Options>/<TextNodeName>
Используйте эти элементы вместе.
Если установлено значение true , содержимое элемента XML преобразуется в строковое свойство.
<TextAlwaysAsProperty>true</TextAlwaysAsProperty> <TextNodeName>TEXT</TextNodeName>
Для следующего XML:
<a> <b>value1</b> <c>value2<d>value3</d>value4</c> </a>
Если для TextAlwaysAsProperty установлено значение true и TextNodeName указано как TEXT , создается следующая структура JSON:
{
"a": {
"b": {
"TEXT": "value1"
},
"c": {
"TEXT": [
"value2",
"value4"
],
"d": {
"TEXT": "value3"
}
}
}
}Если для TextAlwaysAsProperty установлено значение false и TextNodeName указано как TEXT , создается следующая структура JSON:
{
"a": {
"b": "value1",
"c": {
"TEXT": [
"value2",
"value4"
],
{
"d": "value3",
}
}
}| По умолчанию | <TextAlwaysAsProperty> : ложь<TextNodeName> : Н/Д |
| Присутствие | Необязательный |
| Тип | <TextAlwaysAsProperty> : логическое значение<TextNodeName> : строка |
<Параметры>/<ИмяБлокаАтрибутов>
Элементы <Options>/<AttributePrefix>
Используйте эти элементы вместе.
Позволяет группировать значения в блок JSON и добавлять префиксы к именам атрибутов.
<AttributeBlockName>FOO_BLOCK</AttributeBlockName> <AttributePrefix>BAR_</AttributePrefix>
Рассмотрим следующий пример XML:
<a attrib1="value1" attrib2="value2"/>
Если оба атрибута ( AttributeBlockName и AttributePrefix ) указаны, как определено в примере XML в JSON, создается следующая структура JSON:
{
"a": {
"FOO_BLOCK": {
"BAR_attrib1": "value1",
"BAR_attrib2": "value2"
}
}
}Если указано только AttributeBlockName , создается следующая структура JSON:
{
"a": {
"FOO_BLOCK": {
"attrib1": "value1",
"attrib2": "value2"
}
}
}Если указан только AttributePrefix , генерируется следующая структура JSON:
{
"a": {
"BAR_attrib1": "value1",
"BAR_attrib2": "value2"
}
}Если ни один из них не указан, создается следующая структура JSON:
{
"a": {
"attrib1": "value1",
"attrib2": "value2"
}
}| По умолчанию | См. примеры выше. |
| Присутствие | Необязательный |
| Тип | Нить |
<Параметры>/<Выходной префикс>
Элементы <Options>/<OutputSuffix>
Используйте эти элементы вместе.
<OutputPrefix>PREFIX_</OutputPrefix> <OutputSuffix>_SUFFIX</OutputSuffix>
Рассмотрим следующий пример XML:
<a>value</a>
Если оба атрибута ( OutputPrefix и OutputSuffix ) указаны, как определено в примере XML в JSON, создается следующая структура JSON:
PREFIX_{
"a": "value"
}_SUFFIXЕсли указан только OutputPrefix , генерируется следующая структура JSON:
PREFIX_{
"a" : "value"
}Если указан только OutputSuffix , генерируется следующая структура JSON:
{
"a" : "value"
}_SUFFIXЕсли не указаны ни OutputPrefix , ни OutputSuffix , создается следующая структура JSON:
{
"a": "value"
}| По умолчанию | См. образцы выше. |
| Присутствие | Необязательный |
| Тип | Нить |
Элемент <Options>/<StripLevels>
<Options>
<StripLevels>4</StripLevels>
</Options>Иногда полезные данные XML, такие как SOAP, имеют множество родительских уровней, которые не следует включать в преобразованный JSON. Вот пример ответа SOAP, содержащего много уровней:
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/Schemata-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <soap:Body> <GetCityWeatherByZIPResponse xmlns="http://ws.cdyne.com/WeatherWS/"> <GetCityWeatherByZIPResult> <State>CO</State> <City>Denver</City> <Description>Sunny</Description> <Temperature>62</Temperature> </GetCityWeatherByZIPResult> </GetCityWeatherByZIPResponse> </soap:Body> </soap:Envelope>
Прежде чем перейти к уровню «Штат», «Город», «Описание» и «Температура», необходимо пройти 4 уровня. Без использования <StripLevels> преобразованный ответ JSON будет выглядеть так:
{
"Envelope" : {
"Body" : {
"GetCityWeatherByZIPResponse" : {
"GetCityWeatherByZIPResult" : {
"State" : "CO",
"City" : "Denver",
"Description" : "Sunny",
"Temperature" : "62"
}
}
}
}
}Если вы хотите удалить эти первые 4 уровня в ответе JSON, вы должны установить <StripLevels>4</StripLevels> , что даст вам следующий JSON:
{
"State" : "CO",
"City" : "Denver",
"Description" : "Sunny",
"Temperature" : "62"
}Вы можете разделить уровни до первого элемента, содержащего несколько дочерних элементов. Что это значит? Давайте посмотрим на более сложный пример JSON:
{
"Envelope" : {
"Body" : {
"GetCityForecastByZIPResponse" : {
"GetCityForecastByZIPResult" : {
"ResponseText" : "City Found",
"ForecastResult" : {
"Forecast" : [
{
"ProbabilityOfPrecipiation" : {
"Nighttime" : "00",
"Daytime" : 10
} ...Уровень 3 в этом примере — GetCityForecastByZIPResponse , у которого есть только один дочерний элемент. Итак, если бы вы использовали <StripLevels>3</StripLevels> (удали первые три уровня), JSON выглядел бы так:
{
"GetCityForecastByZIPResult" : {
"ResponseText" : "City Found",
"ForecastResult" : {
"Forecast" : [
{
"ProbabilityOfPrecipiation" : {
"Nighttime" : "00",
"Daytime" : 10
} ...Обратите внимание, что GetCityForecastByZIPResult имеет несколько дочерних элементов. Поскольку это первый элемент, содержащий несколько дочерних элементов, вы можете удалить этот последний уровень с помощью <StripLevels>4</StripLevels> , что даст вам следующий JSON:
{
"ResponseText" : "City Found",
"ForecastResult" : {
"Forecast" : [
{
"ProbabilityOfPrecipiation" : {
"Nighttime" : "00",
"Daytime" : 10
} ...Поскольку уровень 4 — это первый уровень, содержащий несколько дочерних элементов, вы не можете удалить уровни ниже этого. Если вы установите уровень полосы на 5, 6, 7 и т. д., вы продолжите получать ответ, указанный выше.
| По умолчанию | 0 (без снятия уровня) |
| Присутствие | Необязательный |
| Тип | Целое число |
Элемент <Options>/<TreatAsArray>/<Path>
<Options>
<TreatAsArray>
<Path unwrap="true">teachers/teacher/studentnames/name</Path>
</TreatAsArray>
</Options>Эта комбинация элементов позволяет гарантировать, что значения из XML-документа будут помещены в массив JSON. Это полезно, например, когда количество дочерних элементов может варьироваться (от одного до нескольких), и вы хотите, чтобы значения всегда находились в массиве. Это помогает поддерживать стабильность вашего кода, поскольку вы можете каждый раз получать данные из массива одним и тем же способом. Например: $.teachers.teacher.studentnames[0] получает значение имени первого ученика в массиве независимо от количества значений в массиве.
Давайте сделаем шаг назад и посмотрим на поведение по умолчанию при преобразовании XML в JSON, а затем выясним, как управлять выводом с помощью <TreatAsArray>/<Path> .
Когда XML-документ содержит элемент с несколькими дочерними значениями (обычно на основе схемы, в которой элемент maxOccurs='unbounded' ), политика XML в JSON автоматически помещает эти значения в массив. Например, следующий блок XML
<teacher>
<name>teacherA</name>
<studentnames>
<name>student1</name>
<name>student2</name>
</studentnames>
</teacher>... автоматически преобразуется в следующий JSON без специальной настройки политики:
{
"teachers" : {
"teacher" : {
"name" : "teacherA",
"studentnames" : {
"name" : [
"student1",
"student2"
]}
}
}
}Обратите внимание, что имена двух студентов помещены в массив.
Однако если в XML-документе отображается только один учащийся, политика XML в JSON автоматически обрабатывает значение как одну строку, а не массив строк, как показано в следующем примере:
{
"teachers" : {
"teacher" : {
"name" : "teacherA",
"studentnames" : {
"name" : "student1"
}
}
}
}В предыдущих примерах аналогичные данные конвертировались по-разному: один раз как массив, другой — как одна строка. Здесь элемент <TreatAsArray>/<Path> позволяет вам управлять выводом. Например, вы можете убедиться, что имена студентов всегда помещаются в массив, даже если имеется только одно значение. Вы настраиваете это, определяя путь к элементу, значения которого вы хотите поместить в массив, например:
<Options>
<TreatAsArray>
<Path>teachers/teacher/studentnames/name</Path>
</TreatAsArray>
</Options>В приведенной выше конфигурации JSON будет записываться следующим образом:
{
"teachers" : {
"teacher" : {
"name" : "teacherA",
"studentnames" : {
"name" : ["student1"]
}
]
}
}
}Обратите внимание, что Student1 теперь находится в массиве. Теперь, независимо от того, есть ли у вас один или несколько учеников, вы можете получить их из массива JSON в своем коде, используя следующий JSONPath: $.teachers.teacher.studentnames.name[0]
Элемент <Path> также имеет атрибут unwrap , описанный в следующем разделе.
| По умолчанию | NA |
| Присутствие | Необязательный |
| Тип | Нить |
Атрибуты
<Options>
<TreatAsArray>
<Path unwrap="true">teachers/teacher/studentnames/name</Path>
</TreatAsArray>
</Options>| Атрибут | Описание | Присутствие | Тип |
|---|---|---|---|
| разворачивать | По умолчанию: ложь Удаляет элемент из вывода JSON. Используйте это, чтобы упростить или сгладить («развернуть») JSON, что также сокращает JSONPath, необходимый для получения значений. Например, вместо Вот пример JSON: {
"teachers" : {
"teacher" : {
"name" : "teacherA",
"studentnames" : {
"name" : [
"student1",
"student2"
]}...В этом примере вы можете возразить, что элемент <TreatAsArray>
<Path unwrap="true">teachers/teacher</Path>
<Path unwrap="true">teachers/teacher/studentnames/name</Path>
</TreatAsArray>Атрибуту {
"teachers" : [{
"name" : "teacherA",
"studentnames" : ["student1","student2"]
}]...Обратите внимание: поскольку элемент | Необязательный | логическое значение |
Дополнительные примеры и описание функций см. в этой статье сообщества Apigee: https://community.apigee.com/content/kbentry/33374/new-edge-minifeature-the-treatasarray-option-in-th.html .
<Формат>
Формат дает вам контроль над преобразованием XML в JSON. Введите имя предопределенного шаблона, содержащего определенную комбинацию элементов параметров, описанных в этом разделе. Предопределенные форматы включают: xml.com , yahoo , google , badgerFish .
Используйте либо элемент <Format> , либо группу <Options> . Вы не можете использовать одновременно <Format> и <Options> .
Ниже приведены определения формата каждого предопределенного шаблона.
xml.com
<RecognizeNull>true</RecognizeNull> <TextNodeName>#text</TextNodeName> <AttributePrefix>@</AttributePrefix>
Yahoo
<RecognizeNumber>true</RecognizeNumber> <TextNodeName>content</TextNodeName>
<TextNodeName>$t</TextNodeName> <NamespaceSeparator>$</NamespaceSeparator> <TextAlwaysAsProperty>true</TextAlwaysAsProperty>
барсукРыба
<TextNodeName>$</TextNodeName> <TextAlwaysAsProperty>true</TextAlwaysAsProperty> <AttributePrefix>@</AttributePrefix> <NamespaceSeparator>:</NamespaceSeparator> <NamespaceBlockName>@xmlns</NamespaceBlockName> <DefaultNamespaceNodeName>$</DefaultNamespaceNodeName>
Синтаксис элемента:
<Format>yahoo</Format>
| По умолчанию | Введите название доступного формата:xml.com , yahoo , google , badgerFish |
| Присутствие | Требуется, если <Options> не используется. |
| Тип | Нить |
Схемы
Ссылка на ошибку
В этом разделе описаны коды ошибок и сообщения об ошибках, которые возвращаются, а также переменные ошибок, которые устанавливаются Edge, когда эта политика вызывает ошибку. Эту информацию важно знать, если вы разрабатываете правила обработки ошибок. Дополнительные сведения см. в разделах Что нужно знать об ошибках политики и Обработка ошибок .
Ошибки выполнения
Эти ошибки могут возникать при выполнении политики.
| Код неисправности | Статус HTTP | Причина | Исправить |
|---|---|---|---|
steps.xmltojson.ExecutionFailed | 500 | Эта ошибка возникает, когда входные полезные данные (XML) пусты или входной XML недействителен или имеет неверный формат. | build |
steps.xmltojson.InCompatibleType | 500 | Эта ошибка возникает, если тип переменной, определенной в элементе <Source> и элементе <OutputVariable> , не совпадает. Обязательно, чтобы тип переменных, содержащихся в элементе <Source> и элементе <OutputVariable> , совпадал. | build |
steps.xmltojson.InvalidSourceType | 500 | Эта ошибка возникает, если тип переменной, используемой для определения элемента <Source> недействителен. Допустимыми типами переменных являются сообщение и строка. | build |
steps.xmltojson.OutputVariableIsNotAvailable | 500 | Эта ошибка возникает, если переменная, указанная в элементе <Source> политики XML для JSON, имеет строковый тип, а элемент <OutputVariable> не определен. Элемент <OutputVariable> является обязательным, если переменная, определенная в элементе <Source> , имеет строковый тип. | build |
steps.xmltojson.SourceUnavailable | 500 | Эта ошибка возникает, если переменная сообщения , указанная в элементе <Source> политики XML в JSON, имеет одно из следующих значений:
| build |
Ошибки развертывания
Эти ошибки могут возникнуть при развертывании прокси-сервера, содержащего эту политику.
| Название ошибки | Причина | Исправить |
|---|---|---|
EitherOptionOrFormat | Если один из элементов <Options> или <Format> не объявлен в политике XML to JSON, развертывание прокси-сервера API завершается неудачей. | build |
UnknownFormat | Если для элемента <Format> в политике XML to JSON определен неизвестный формат, развертывание прокси-сервера API завершается неудачей. Предопределенные форматы включают: xml.com , yahoo , google и badgerFish . | build |
Переменные неисправности
Эти переменные устанавливаются при возникновении ошибки во время выполнения. Дополнительные сведения см. в разделе Что нужно знать об ошибках политики .
| Переменные | Где | Пример |
|---|---|---|
fault.name=" fault_name " | fault_name — это имя ошибки, как указано в таблице ошибок времени выполнения выше. Имя неисправности — это последняя часть кода неисправности. | fault.name = "SourceUnavailable" |
xmltojson. policy_name .failed | policy_name — указанное пользователем имя политики, вызвавшей ошибку. | xmltojson.XMLtoJSON-1.failed = true |
Пример ответа об ошибке
{ "fault": { "faultstring": "XMLToJSON[XMLtoJSON-1]: Source xyz is not available", "detail": { "errorcode": "steps.xml2json.SourceUnavailable" } } }
Пример правила неисправности
<faultrule name="VariableOfNonMsgType"></faultrule><FaultRule name="XML to JSON Faults"> <Step> <Name>AM-SourceUnavailableMessage</Name> <Condition>(fault.name Matches "SourceUnavailable") </Condition> </Step> <Step> <Name>AM-BadXML</Name> <Condition>(fault.name = "ExecutionFailed")</Condition> </Step> <Condition>(xmltojson.XMLtoJSON-1.failed = true) </Condition> </FaultRule>
Связанные темы
JSON в XML: политика JSON в XML