недопустимый символ xml на SQL Insert

Я пытаюсь вставить следующую строку в поле SQL xml

<?xml version="1.0" encoding="UTF-8"?>
<Response> 
    <Ip>x.x.x.x</Ip>
    <CountryCode>CA</CountryCode> 
    <CountryName>Canada</CountryName>
    <RegionCode>QC</RegionCode> 
    <RegionName>Québec</RegionName> 
    <City>Dorval</City> 
    <ZipCode>h9p1j3</ZipCode> 
    <Latitude>45.45000076293945</Latitude> 
    <Longitude>-73.75</Longitude> 
    <MetroCode></MetroCode> 
    <AreaCode></AreaCode> 
</Response>

код вставки выглядит так:

INSERT 
    INTO Traffic(... , xmlGeoLocation, ...)
    VALUES (
        ...
        <!--- 
        <cfqueryparam CFSQLType="cf_sql_varchar" value="#xmlGeoLocation#">, 
        --->
        '#xmlGeoLocation#',

        ...
        )

случаются две плохие вещи:

  1. Квебек превращается в Québec

  2. Я получаю сообщение об ошибке говорящее [Macromedia][SQLServer JDBC Driver][SQLServer]XML parsing: line 8, character 16, illegal xml character

обновление:

входящий тестовый поток состоит в основном из однобайтовых символов.

é-двухбайтовый символ. Особенно C3A9

также у меня нет контроля над входящим потоком xml

3 ответов


Я собираюсь снять заголовок...

у меня такая же проблема с забавным маленьким Апострофом. Я думаю, проблема в том, что к тому времени, когда строка преобразуется в XML, она больше не UTF-8, но sql server пытается использовать заголовок для ее декодирования. Если это VARCHAR, то в кодировке клиента. Если это NVARCHAR, то UTF-16. Вот некоторые варианты, которые я тестировал:

SQL (varchar, UTF-8):

SELECT CONVERT(XML,'<?xml version="1.0" encoding="UTF-8"?><t>We’re sorry</t>')

ошибка:

XML parsing: line 1, character 44, illegal xml character

SQL (nvarchar, UTF-8):

SELECT CONVERT(XML,N'<?xml version="1.0" encoding="UTF-8"?><t>We’re sorry</t>')

ошибка: Синтаксический анализ XML: строка 1, символ 38, невозможно переключить кодировку

SQL (varchar, UTF-16)

SELECT CONVERT(XML,'<?xml version="1.0" encoding="UTF-16"?><t>We’re sorry</t>')

ошибка:

XML parsing: line 1, character 39, unable to switch the encoding

SQL (nvarchar, UTF-16)

SELECT CONVERT(XML,N'<?xml version="1.0" encoding="UTF-16"?><t>We’re sorry</t>')

работала!


попробуйте изменить это:

<RegionName>Québec</RegionName> 

в:

<RegionName><![CDATA[Québec
]]></RegionName> 

посмотри ссылке из w3 он говорит мне, что:

в HTML есть список некоторых встроенных имен символов, таких как &eacute; для é, но XML не имеет этого. В XML существует только пять встроенных символьных сущностей:&lt;, &gt;, &amp;, &quot; и &apos; Для , &, " и ' соответственно. Можно определить собственные сущности в определении типа документа или использовать любой символ Юникода (см. Следующий элемент).

в HTML, есть также числовые ссылки на символы, такие как &#38; для &. Вы можете ссылаться на любой символ Юникода, но число десятичное, тогда как в таблицах Юникода число обычно шестнадцатеричное. XML также позволяет шестнадцатеричные ссылки:&#x26; например.

это заставляет меня поверить, что,&#xE9; может работать для символа é.

также информация на этом ссылке из Штатов Microsoft что:

SQLXML 4.0 полагается на ограниченную поддержку DTDs, предоставляемую в SQL Server. SQL Server допускает наличие внутреннего DTD в xml-данных типа данных, которые могут использоваться для предоставления значений по умолчанию и замены ссылок на сущности их расширенным содержимым. SQLXML передает XML-данные "как есть" (включая внутренний DTD) на сервер. Вы можете конвертировать DTDs в документы XML-схемы (XSD) с помощью сторонних инструментов и загружать данные с помощью встроенных схем XSD в база данных.

но все это не поможет вам, если у вас нет контроля над входящим потоком XML. Я сомневаюсь, что можно сохранить é (или любой специальный символ, за исключением встроенных символьных сущностей, упомянутых выше) внутри XML-документа в XML-поле SQL Server, не добавляя DTD или не заменяя символ его шестнадцатеричным ссылочным аналогом. В обоих случаях вам нужно будет иметь возможность изменить XML, прежде чем он пойдет в базу данных.

просто быстрый пример для тех, кто хочет спуститься по маршруту "добавление DTD".

вот как добавить внутренний DTD в xml-файл, который объявляет сущность для символа é:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY eacute "&#233;">]>
<root>
  <RegionName>Qu&eacute;bec</RegionName>
</root>

если вы идете здесь и поиск на странице "Ctrl+F" для "eacute", вы попадаете в список с примерами для других символов, которые вы можете просто скопировать и вставить в свой собственный внутренний шаблон DTD.

редактировать

вы можете, конечно, добавить все объекты, как они указаны в ссылке выше: <!ENTITY eacute "&#233;"><!ENTITY .. // Next entity>, или просто скопируйте их все из этого . Я понимаю, как добавление внутреннего DTD в каждый XML-файл, который вы добавляете в базу данных, не такая хорошая идея. Мне было бы интересно узнать, исправляет ли добавление его для файла 1 вашу проблему.