danielbodensee
Goto Top

Problem mit Invoke-Sqlcmd und UTF-16 XML

Hallo,

ich beschäftige mich noch nicht so lange mit dem Abfüllen von Daten in eine SQL-Datenbank, soweit klappt alles was ich brauche.

Nun habe ich ein Problem beim insert um den Inhalt eines XML-Files in eine Tabelle mit XML-Feld abzulegen. Zur Interaktion mit SQL nehme ich "Invoke-Sqlcmd".

Alle XML-Inhalte ohne Emcoding klappt es, diese werden (wie mir erlesen habe) als UTF-8 encoded. Bekomme ich nun ein File mit UTF-16 zum einlesen, bekomme ich den Fehler:

Invoke-Sqlcmd : XML parsing: line 1, character 39, unable to switch the encoding 
 Msg 9402, Level 16, State 1, Procedure , Line 2.
At G:\CleanUp_Dani3\Main7.ps1:659 char:17
+ ...             Invoke-Sqlcmd -Querytimeout 10 -Query $SqlQuery -ServerIn ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Invoke-Sqlcmd], SqlPowerShellSqlExecutionException
    + FullyQualifiedErrorId : SqlError,Microsoft.SqlServer.Management.PowerShell.GetScriptCommand

Ich schaffe es nicht von UTF-16 zu UTF-8 zu konvertieren, also dachte ich den Header (wenn UTF-16 auftaucht) zu löschen, aber das klappt auch nicht.

Zum testen habe ich mir eine Variable erstellt mit einem Test-Inhalt für ein XML-File:
[xml]$XmlFile=
'<?xml version="1.0" encoding="UTF-16"?> 
<Prim>
    <Custommer Name="Kunde 1" ID="147" Phone="01235/6789"/> 
</Prim>' 

Könntet Ihr mir bitte zeigen wie ich entweder auf UTF-8 konvertieren kann oder den Header (wenn encoding auftritt) zu löschen?

Wäre Euch für die Hilfe sehr dankbar.

Viele Grüsse,
Daniel

Content-Key: 6989426711

Url: https://administrator.de/contentid/6989426711

Printed on: February 29, 2024 at 23:02 o'clock

Member: abramakabra
Solution abramakabra Feb 13, 2024 updated at 08:45:55 (UTC)
Goto Top
Encoding in Declaration weg/ändern
$xmlfile.ChildNodes | ?{$_.NodeType -eq 'XmlDeclaration' -and $_.Encoding} | %{$_.Encoding = ''}  
https://tio.run/##TY5Pa8JAEMXv@ymGJWVPSUxrYwtZI2gFKYgHC4VSSnCnzcL@sZuktV ...

Oder XML Declaration ganz weg
$xmlfile.ChildNodes | ?{$_.NodeType -eq 'XmlDeclaration' -and $_.Encoding} | %{[void]$xmlfile.RemoveChild($_)}  
https://tio.run/##TY5bS8NAEIXf91cMSyT2IUmj9gZJU2gtiFCKtFAopYTuaBb2UjcXld ...

String von UTF-16 auf UTF-8 konvertieren
[System.Text.UTF8Encoding]::GetString([System.Text.UnicodeEncoding]::GetBytes($string))

Oder das Feld in der DB auf einen binary blob stellen.
Member: DanielBodensee
DanielBodensee Feb 13, 2024 at 12:27:46 (UTC)
Goto Top
Hi abramakabra,

vielen Dank für die Hilfe face-smile

Ich habe mich für das entfernen der Declation entschieden, habe das erst getestet und dann in mein Script eingebaut. Tja, es lief nicht schlecht, doch nun habe ich den Fehler das ich auch Angaben im XML-File habe wo in einem Feld ein Apostrophe auftaucht (Kunden-Name wie zum Beispiel D'Agosto).

Damit hatte ich quasi das nächste Problem face-smile

Ich habe es mal so gelöst (für mich am einfachsten):
# Entfernen der XML Declaration wenn vorhanden (Insert in SQL bei UTF-16 erzeugt Fehler)
if ($XmlFile.FirstChild.Encoding -eq 'UTF-16') {  
                    
    # Entfernen der XML Declaration
    $XmlFile.ChildNodes | ?{$_.NodeType -eq 'XmlDeclaration' -and $_.Encoding} | %{[void]$XmlFile.RemoveChild($_)}  

    # Ersetzen Single-Apostrophe
    $XmlFile=$XmlFile.InnerXml.Replace("'","''")  
}

Geht es auch eleganter?
Member: abramakabra
abramakabra Feb 13, 2024 updated at 12:35:04 (UTC)
Goto Top
Besser gleich ein Binary-Feld benutzen dann entfällt auch das futeln em Encoding oder die XML vorher in Base64 kodieren und dann wegschreiben, so riecht das nach sonst schon nach fieser (unbeabsichtigter) SQL-Injection-Möglichkeit.