LINUX.ORG.RU

Как при помощи QDomDocument вставить XML в качестве значения поля?

 , ,


0

1

Привет, лор.

Мне нужно вставить XML-документ в одно из полей другого XML-документа. Это не моя прихоть, так требует ТЗ:)

Делаю это так:

	// создаю внешний документ
	QDomDocument doc;
	doc.appendChild(doc.createProcessingInstruction("xml", "version=\"1.0\"" ));
	auto item = doc.createElement("item");
	doc.appendChild(item);

	// создаю вложенный документ
	QDomDocument innerDoc;
	innerDoc.appendChild(innerDoc.createElement("foo"));
	innerDoc.appendChild(innerDoc.createElement("bar"));

	// вставляю вложенный документ
	QDomText nameText = doc.createTextNode("xml");
	item.appendChild(nameText);

Всё получается, вложенный xml эскейпится, но есть проблема. Не эскейпится символ «>». Получается, что xml выглядит вот так:

<?xml version="1.0"?>
<item>
   <xml>&lt;foo/>
&lt;bar/>
</xml>
</item>

Я даже нашёл баг, посвящённый этой проблеме: https://bugreports.qt.io/browse/QTBUG-16020. Баг старый, закрыт как invalid. Там написано, что такое поведение правильное, и соответствует стандарту XML.

К сожалению, тот софт, который принимает сформированные мной документы, не согласен с этим, и не понимает мои документы. Поэтому нужно как-то это побороть. Если заэскейпить строку вручную, до передачи её в createTextNode(), она эскейпится снова, и получается совсем плохо.

Мне бы помогла какая-нибудь функция в QDom, которая позволяет вставить произвольный текст.

Или может быть можно как-то взять qdom.cpp и qdom.h, скопировать к себе в проект и поправить под себя?

В общем, жду идей.


По идее, тебе надо вставлять данные, как cdata.

hippi90 ★★★★★ ()

Или может быть можно как-то взять qdom.cpp и qdom.h,

Там много приватных хедеров. Не получится. Как и с любыми другими Qt классами.

RazrFalcon ★★★★★ ()
Ответ на: комментарий от RazrFalcon

Если вам нужно экранирование - используйте https://doc.qt.io/qt-5/qstring.html#toHtmlEscaped

Да я бы рад:) Вопрос, как вставить результат toHtmlEscaped в xml.

Сейчас выкрутился так: вставляю вместо xml волшебное слово («PLACE XML HERE»), преобразую внешний xml в строку, и уже в этой строке заменяю волшебное слово на результат toHtmlEscaped. Коряво, но хоть как-то работает.

Beewek ()
Ответ на: комментарий от deep-purple

Тебе же сказали как сделать правильно: CDATA

Нет, CDATA не подходит. Я же написал в начальном посте: надо вставить XML в поле другого XML. Это требование стандарта того протокола, который я реализую. Если бы XML можно было вложить в CDATA, вопроса бы не возникло.

Beewek ()
Ответ на: комментарий от LongLiveUbuntu

Да, я понял это предложение:)

Нет, это предложение мне не подходит. Нужно чтобы было без CDATA. Такое требование.

Beewek ()
Ответ на: комментарий от Beewek

надо вставить XML в поле другого XML

Либо ты вставляешь только root-элемент со всем его содержимым, но тогда теряешь версию, кодировку, шему и доктайп. Либо ты вставляешь весь XML в CDATA полностью как текст.

Это требование стандарта того протокола, который я реализую

Или ты чего-то не договариваешь или этот протокол придумывали дебилы.

deep-purple ★★★★★ ()
Последнее исправление: deep-purple (всего исправлений: 2)
Ответ на: комментарий от Beewek

мне не подходит. Нужно чтобы было без CDATA. Такое требование

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

CDATA даёт тот же эффект, правда, немного другим способом, но она есть в спеках XML и гарантированно будет разобрана любым парсером.

deep-purple ★★★★★ ()
Ответ на: комментарий от deep-purple

CDATA даёт тот же эффект, правда, немного другим способом, но она есть в спеках XML и гарантированно будет разобрана любым парсером.

Парсером то может и поддерживается, а вот теми кто этот парсер использует не обязательно.

anonymous ()
Ответ на: комментарий от deep-purple

CDATA даёт тот же эффект, правда, немного другим способом, но она есть в спеках XML и гарантированно будет разобрана любым парсером.

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

Я ж говорю — дебилы (исходя из того что описал ТС).

Мне тоже не очень нравится этот стандарт (eсли интересно, то речь о WITSML). Но уж что есть, то есть.

Beewek ()
Ответ на: комментарий от RazrFalcon

Да, я так и сделал (написал выше). Странно, что в QDomDocument не предусмотрена возможность вставить в ноду произвольный текст.

Beewek ()
Ответ на: комментарий от Beewek

Ничего странного, так как это приведёт к генерации кривого xml.

RazrFalcon ★★★★★ ()
Ответ на: комментарий от Beewek

Лень сейчас колупать спеки, но:

WITSML Standards are defined using the W3C Internet standards for XML (notably XML Schema) and Web Services (including SOAP and WSDL)).

указывает что CDATA прокатит на ура.

Но, чтобы удостовериться в этом, давай, рассказывай зачем кому понадобилось заворачивать в один ответ множество других ответов ))

deep-purple ★★★★★ ()
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от deep-purple

указывает что CDATA прокатит на ура.

Не факт. Данный стандарт может использовать подмножество стандартов XML, SOAP и WSDL, при этом обходясь без CDATA. Собственно, в тексте нет упоминания о CDATA. И в примерах запросов и ответов - тоже нет.

Но, чтобы удостовериться в этом, давай, рассказывай зачем кому понадобилось заворачивать в один ответ множество других ответов ))

Не обязательно множество, чаще один xml-параметр. Там всё просто: идёт обмен документами (запрос-ответ), и каждый документ состоит из конверта и собственно содержимого. Сам документ - xml, и содержимое - тоже может быть xml. Вот пример запроса:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
   xmlns:ns3="http://www.w3.org/2001/XMLSchema"
   xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/
   xmlns:ns0="http://schemas.xmlsoap.org/soap/encoding/"
   xmlns:ns1="http://www.witsml.org/message/120"
   xmlns:ns2="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
   SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
   <SOAP-ENV:Header/>
   <ns2:Body>
      <ns1:WMLS_GetFromStore>
         <WMLtypeIn xsi:type="ns3:string">well</WMLtypeIn>
         <QueryIn xsi:type="ns3:string">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
                                     &lt;wells xmlns=&quot;http://www.witsml.org/schemas/1series&quot; version=&quot;1.4.1.1&quot;&gt;
                                         &lt;well uid=&quot;Energistics-well-0001&quot;&gt;
                                           &lt;name/&gt;
                                           &lt;commonData&gt;
                                             &lt;dTimLastChange/&gt;
                                           &lt;/commonData&gt;
                                         &lt;/well&gt;
                                     &lt;/wells&gt;
                                  </QueryIn>
         <OptionsIn xsi:type="ns3:string"></OptionsIn>
         <CapabilitiesIn xsi:type="ns3:string"></CapabilitiesIn>
      </ns1:WMLS_GetFromStore>
   </ns2:Body>
</SOAP-ENV:Envelope>

WMLS_GetFromStore - тип запроса, вложенные элементы - параметры. Один из параметров - QueryIn - тоже xml-документ.

Beewek ()
Ответ на: комментарий от Beewek

содержимое - тоже может быть xml

Но:

QueryIn xsi:type=«ns3:string»

Чот не сходится. Ну, т.е. сходится, но не на том уровне абстракции.

А не морочил ли ты нам головы своим не правильно поставленным вопросом?

Тип указан — строка. Но! При получении такого ответа, строка должна в любом случае быть оттуда выдрана, а затем над ней нужны дополнительные манипуляции, чтобы превратить её в XML, распарсить и только потом применить по назначению.

Мне всё еще думается что ты не знаешь что творишь, ну или не ты, а тот кто поставил тебе такую задачу. Попробуй ответить на вопросы:

1) Позволяет ли WITSML иметь XML внутри XML?
2) Если позволяет, то, каким способом указано делать этот финт в спеках/шемах WITSML — root-элемент/эскейпинг/CDATA/другаяэкранирующаяхерня?
3) Какие парсеры WITSML и/или ПО их использующее поддерживают такое?
4) Или три предыдущих вопроса не имеют смысла, т.к. чья-то больная фантазия возжелала расширить протокол здесь и сейчас, потому что так хочется, а это влечет за собой несовместимость с другим ПО и надо как-то выкручиваться?

Ответь на все 4 вопроса без фраз типа «не знаю» или «полагаю».

deep-purple ★★★★★ ()
Ответ на: комментарий от deep-purple

1) Позволяет ли WITSML иметь XML внутри XML?

Да, не только позволяет, но даже требует. Там описан API, используемый для запроса к серверам. И часть параметров в запросах и ответах этого API являются XML-документами. Выше я привёл пример запроса, который формируется средством для сертификации серверов.

2) Если позволяет, то, каким способом указано делать этот финт в спеках/шемах WITSML — root-элемент/эскейпинг/CDATA/другаяэкранирующаяхерня?

Явно никак не указано. Но в эталонной реализации (https://github.com/pds-technology/witsml), которой, по сути, пользуются все клиентские программы, используется эскейпинг.

3) Какие парсеры WITSML и/или ПО их использующее поддерживают такое?

Насколько я знаю, все. Там есть программа сертификации серверов, и софт для этой сертификации () делает именно так.

4. Стандарт этот действует довольно давно, и имеется приличное количество софта, который использует этот стандарт. Почему один xml вставляют в другой в виде строки - я не знаю. Но это так. Видимо, авторам очень нравится XML:)

В общем, большое спасибо за обсуждение, свою проблему я кое-как решил, и к тому же получил несколько новых идей. Обсуждать же кривизну стандарта не вижу особого смысла - вряд ли авторы почитают лор и бросятся его переделывать:)

Beewek ()
Ответ на: комментарий от Beewek

Почему один xml вставляют в другой в виде строки - я не знаю.

Я видел и похуже извращение - XML, одним из полей которого является... длина самого этого XML-файла. Чтобы установка этого поля не влияла на длину, оно представлено как строка из 10 символов (берётся строковое значение длины файла и добивается до 10 символов пробелами). Если что — речь про файлы UDX (файл резервной копии некоторых телефонов Philips).

hobbit ★★★★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.