2013-04-14 20 views
6

Próbuję wstawić następujący ciąg na sql polu xmlnielegalne xml postać na INSERT

<?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> 

Kod wkładka wygląda następująco:

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

     ... 
     ) 

Dwa złych rzeczy się stało:

  1. Québec zostaje zmieniony na Quà © bec

  2. pojawia się błąd mówiący [Macromedia][SQLServer JDBC Driver][SQLServer]XML parsing: line 8, character 16, illegal xml character

UPDATE:

Przychodzące strumień test jest głównie pojedynczych znaków bajtowych.

Znak é jest znakiem dwubajtowym. W szczególności C3A9

Również nie mam kontroli nad przychodzącego strumienia xml

+1

I * think * serwer sql używa kodowania utf-16, a deklaracja 'utf-8' w xml jest przyczyną niepowodzenia. FWIW, jeśli całkowicie usuniesz deklarację "kodowania" lub zmienisz ją na "encoding =" UTF-16 ", wstawienie powiedzie się w CF10, z włączoną opcją" Włącz wysokie znaki ASCII ... ". (Zmiana kodowania tylko łańcucha nie przyniosła skutku.) Jednak nie wiem, czy ma to negatywny wpływ na stronę. – Leigh

+0

Uwaga, kodowanie znaków jest * nie * moje hasło ;-) Powyższy komentarz jest oparty tylko na kilku szybkich testach. To nie jest solidna odpowiedź, ale mam nadzieję, że pomoże wskazać ci właściwy kierunek. – Leigh

+0

Jak otrzymujesz XML? Brzmi dla mnie tak, jakbyś nie mówił CF, że to UTF-8. –

Odpowiedz

1

Zapraszamy do obejrzenia tej link od w3, mówi mi, że:

In HTML, there is a list of some built-in character names like &eacute; for é but XML does not have this. In XML, there are only five built-in character entities: &lt; , &gt; , &amp; , &quot; and &apos; for <, >, &, " and ' respectively. You can define your own entities in a Document Type Definition, or you can use any Unicode character (see next item).

In HTML, there are also numeric character references, such as &#38; for &. You can refer to any Unicode character, but the number is decimal, whereas in the Unicode tables the number is usually in hexadecimal. XML also allows hexadecimal references: &#x26; for example.

To prowadzi mnie do przekonania, że ​​&#xE9; może działać dla é postaci.

Również informacje na ten link firmy Microsoft stwierdza, że:

SQLXML 4.0 relies upon the limited support for DTDs provided in SQL Server. SQL Server allows for an internal DTD in xml data type data, which can be used to supply default values and to replace entity references with their expanded contents. SQLXML passes the XML data "as is" (including the internal DTD) to the server. You can convert DTDs to XML Schema (XSD) documents using third-party tools, and load the data with inline XSD schemas into the database.

Ale to wszystko nie pomoże, jeśli nie masz kontroli nad przychodzącym strumieniu XML. Wątpię, czy możliwe jest zapisanie é (lub jakiejkolwiek specjalnej postaci w tym przypadku, z wyjątkiem wbudowanych jednostek znakowych wymienionych powyżej) wewnątrz dokumentu XML do pola XML serwera SQL, bez dodawania DTD lub zastępowania znaku przez jego szesnastkowy odpowiednik. W obu przypadkach konieczne będzie umożliwienie modyfikacji kodu XML zanim trafi on do bazy danych.

Po prostu szybki przykład dla każdego, kto chce zejść z trasy "dodając DTD".

Oto jak dodać wewnętrzną DTD do pliku XML, który deklaruje podmiot na znak E:

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

Jeśli pójdziesz here i szukać na stronie „Ctrl + F” za „eacute” trafisz na listę z przykładami innych postaci, które możesz po prostu skopiować i wkleić do własnego wewnętrznego DTD.

Edit

Mogłeś poza oczywiście dodać wszystkie podmioty, jak zostały one określone w link powyżej: <!ENTITY eacute "&#233;"><!ENTITY .. // Next entity>, lub po prostu skopiować je wszystkie z tego file. Rozumiem, że dodanie wewnętrznego DTD do każdego pliku XML dodanego do bazy danych nie jest dobrym pomysłem. Byłbym zainteresowany, aby dowiedzieć się, czy dodanie go do pliku 1 rozwiązuje problem.

+0

Jestem zaniepokojony tym, co dzieje się, gdy pojawia się następny znak specjalny. –

+0

Edytowałem odpowiedź, aby odpowiedzieć na twój komentarz, to naprawdę nie jest rozwiązanie, ale zastanawiam się, czy któreś z nich pozwala wstawić XML ze specjalnym znakiem. –

+0

Twoje rozwiązanie rozwiązuje zadane pytanie, ale naprawdę potrzebuję ogólnego rozwiązania. –

1

próbować zmienić to:

<RegionName>Québec</RegionName> 

do:

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

Nie kontroluję przychodzącego strumienia xml –

9

mam zamiar rozebrać nagłówek ...

Mam ten sam problem ze śmiesznym małym apostrof rzeczy. Myślę, że problem polega na tym, że do czasu, gdy ciąg staje się konwertowany na XML, to już nie jest UTF-8, ale serwer sql próbuje użyć nagłówka do jego odkodowania. Jeśli jest to VARCHAR, jest to kodowanie klienta. Jeśli jest to NVARCHAR, to jest to UTF-16. Oto niektóre warianty testowanego:

SQL (VARCHAR UTF-8)

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

błędu:

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>') 

Błąd: Analizy XML: wiersz 1, znak 38, nie można zmienić kodowania

SQL (varchar, UTF-16)

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

Błąd:

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>') 

działa!

+0

Działa również! Dzięki za rozwiązanie. –

+0

Ze względu na wymuszony przepływ pracy użyliśmy zasad twojej odpowiedzi i zastąpiliśmy nagłówek po otrzymaniu go jako varchar (max) jak ten @webtemp = REPLACE (@webtemp, '", " '). Oczywiście może wymagać dostosowania. To zadziałało. –