AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Probleme mit XML Encoding

Ein Thema von tofse · begonnen am 25. Jan 2018 · letzter Beitrag vom 25. Jan 2018
Antwort Antwort
tofse

Registriert seit: 6. Jun 2011
Ort: Saarlouis
128 Beiträge
 
Delphi XE Professional
 
#1

Probleme mit XML Encoding

  Alt 25. Jan 2018, 14:04
Hallo,
ein Fremdprogramm X exportiert XML Dateien. Diese soll mein Programm verarbeiten. Ich habe keine Möglichkeit, auf den Export Einfluss zu nehmen.
Aufgebaut sind die Dateien immer gleich

Code:
<HEDX>
<BODY>
<ExportType>Export</ExportType>
<SWVersion>
<Name>Viewing Module</Name>
<Version>6.5.7.0</Version>
</SWVersion>
<Patient>
<PatientUIDList>
<NumUIDs>1</NumUIDs>
<PatientUID>
<Source>LOC1456211344</Source>
<UID>LOC1456211344.418d33f0-10c5-4445-8a20-f3bd5f62190b</UID>
</PatientUID>
</PatientUIDList>
<ID>3005</ID>
<PID>200115203</PID>
<LastName>Müller</LastName>
<FirstNames>Franz</FirstNames>
usw.

Mein Code
Delphi-Quellcode:
procedure Te2e.starteVerarbeitung;
var Xml : IXMLDocument;

begin
  Xml:=newXMLDocument;
  try
        Xml.Encoding:='UTF-8';
        Xml.LoadFromFile(FXml);

        Xml.Active:=True;
Es gibt nun ein Problem mit den Umlauten, als Exception erscheint immer

Erste Gelegenheit für Exception bei $7576C54F. Exception-Klasse EDOMParseError mit Meldung
'Im Textinhalt wurde ein ungültiges Zeichen gefunden.

Zeile: 18
<LastName>M'.


Ich hatte es auch schon mit LoadFromStream versucht, da kann man das Encoding ja auch mit angeben, aber das gleiche Problem
Hat jemand eine Idee?

Gruß
  Mit Zitat antworten Zitat
Fukiszo
(Gast)

n/a Beiträge
 
#2

AW: Probleme mit XML Encoding

  Alt 25. Jan 2018, 14:07
das umlaut löst den fehler aus, das sollte wahrscheinlich berücksichtigt werden.

Grüße
  Mit Zitat antworten Zitat
tofse

Registriert seit: 6. Jun 2011
Ort: Saarlouis
128 Beiträge
 
Delphi XE Professional
 
#3

AW: Probleme mit XML Encoding

  Alt 25. Jan 2018, 14:08
Das hatte ich ja geschrieben
"Es gibt nun ein Problem mit den Umlauten"
Nur wie gehe ich damit um?
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
6.822 Beiträge
 
Delphi 10.3 Rio
 
#4

AW: Probleme mit XML Encoding

  Alt 25. Jan 2018, 14:14
Versuch mal

  Xml.Encoding:='windows-1252';
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
tofse

Registriert seit: 6. Jun 2011
Ort: Saarlouis
128 Beiträge
 
Delphi XE Professional
 
#5

AW: Probleme mit XML Encoding

  Alt 25. Jan 2018, 14:15
Leider der gleiche Fehler
  Mit Zitat antworten Zitat
Fukiszo
(Gast)

n/a Beiträge
 
#6

AW: Probleme mit XML Encoding

  Alt 25. Jan 2018, 14:24
damit wollt ich andeuten, du kennst ja dein problem und wollt auf soetwas in etwa hinaus, einen xml parser

Zitat:
Title: XML File Viewer

Question: How to create a simple XML File viewer, without worrying about the XML itself. The easiest solution is using the Microsoft XML Document Object Model, installed on every machine that run MS Internet Explorer 4 or higher.

Answer:
In this article I am showing you a simple XML file viewer, that may be extended to an XML editor with some work. You may enhance the editor by importing icons for the different node types, etc. That's up to you.

My main idea is to show you how to import type libraries from readily available components installed on nearly every machine in the modern windows world.

Note: The MS XML DOM is available for free download and redistribution at msdn.microsoft.com.

IMPORTING THE MS XML TYPE LIBRARY
=================================

Start Delphi and create a new application, I you haven't done so already. In the Delphi menu go to Project|Import Type Library... A dialog will appear on your screen, with a list of all installed and registered COM libraries available for import. Take a moment and scroll through it, you might be surprised.

Somewhere down the list you find Microsoft XML, version 2.0 (Version 2.0). This is the type library we are going to import. Additionally, you may see Microsoft XML, v3.0 (Version 3.0). This is a newer and faster version from MS, we are going to use the older version however, since it is more common.

After selecting the MS XML, version 2.0 component object, select a Unit Directory, and press the Create Unit button. The Install button will install the component in your Component Pallete, additionally.

PREPARING YOUR APPLICATION FORM
===============================

Drop a MainMenu (Standard) component on your form, and insert a Open Menu item (name: Open1).
Drop a TreeView (Win32) component on your form, set Align=alLeft and ReadOnly=True (name: trvStructure).
Drop an OpenDialog (Dialogs) component on your form (name: OpenDialog1).
Drop a Panel (Standard) component on your form, set Align=alClient and clear the Caption (name: Panel1).
Drop a StringGrid (Additional) component on the Panel1 set Align=alTop, RowCount=2, ColCount=2, FixedCols=0, FixedRows=1 (name: grdAttributes).
Drop a Memo (Standard) on the Panel1 set Align=alClient, ReadOnly=True (name mmoNodeContent).

Note: The names I have used will appear in the source code again!

A PSEUDO CLASS FOR THE XML INTERFACES
=====================================

Because mapping of interface via pointers introduces some problems I chose to create a simple class that contains only on variable holding the reference to the XML Node interface.

type
TXMLNodeWrapper = class
private
FNode: IXMLDOMNode;
protected
public
constructor Create(aNode: IXMLDOMNode);
property Node: IXMLDOMNode read FNode;
end;

The constructor will save the reference in the FNode variable.

CREATING THE XML DOM OBJECT
===========================

Creating an instance of the object is rather simple. Having a variable FDocument of the type IXMLDOMDocument, defined in the imported MSXML_TLB.

FDocument := CoDOMDocument.Create;

Next you need to set up the component to your needs.

FDocument.async := False;
FDocument.validateOnParse := True;
FDocument.preserveWhiteSpace := True;

The first I want to do is inserting an base element into the document. Every XML document needs at least this base element. I have named it xmlstart.

Note: Be careful, XML is case-sensitive.

FDocument.appendChild(FDocument.createNode(NODE_EL EMENT, 'xmlstart', ''));

PARSING THE XML DOCUMENT
========================

There are quite many ways of parsing XML. I want to show you two recursive ways, that are very similar, but have quite different results.

(1) NodeList := Node.childNodes;

Returns all children, inlcude some special node types, such as #text or #comment. These node types require special care.

(2) NodeList := Node.selectNodes('*');

Returns all standard node types, that can be accessed via XSL (XML Structured Language). These node types are easy in use.

ACCESSING THE NODE LIST
=======================

Accessing any item in a Node List is very easy. The length returns the count of items in the list (equal to Delphis Count property). The Item array gives access to every Item of the node list.

for I := 0 to Pred(XMLNodeList.length) do
ShowMessage(XMLNodeList.item[I].nodeName);

MORE INFORMATION ABOUT THE MS XML DOM
=====================================

The most important web addresses for the MS XML DOM are:

http://msdn.microsoft.com/xml (all about XML)
http://131.107.228.20/xquerydemo/demo.aspx (XML Query Language Demo)
http://msdn.microsoft.com/downloads/.../072/topic.xml (Downloads)

THE SOURCE CODE FOR THE XML VIEWER
==================================

unit uMainForm;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
MSXML_TLB, ComCtrls, Menus, Grids, ExtCtrls, StdCtrls;

type
TXMLNodeWrapper = class
private
FNode: IXMLDOMNode;
protected
public
constructor Create(aNode: IXMLDOMNode);
property Node: IXMLDOMNode read FNode;
end;

TfrmMain = class(TForm)
MainMenu1: TMainMenu;
File1: TMenuItem;
Open1: TMenuItem;
trvStructure: TTreeView;
OpenDialog1: TOpenDialog;
Panel1: TPanel;
grdAttributes: TStringGrid;
mmoNodeContent: TMemo;
procedure FormCreate(Sender: TObject);
procedure Open1Click(Sender: TObject);
procedure trvStructureChange(Sender: TObject; Node: TTreeNode);
private
FDocument: IXMLDOMDocument;
FFileName: String;
procedure LoadXML;
public
end;

var
frmMain: TfrmMain;

implementation

{$R *.DFM}

{ TXMLNodeWrapper }

constructor TXMLNodeWrapper.Create(aNode: IXMLDOMNode);
begin
inherited Create;
FNode := aNode;
end;

{ TFrmMain }

procedure TfrmMain.FormCreate(Sender: TObject);
begin
FDocument := CoDOMDocument.Create;
FDocument.async := False;
FDocument.validateOnParse := True;
FDocument.preserveWhiteSpace := True;
FDocument.appendChild(FDocument.createNode(NODE_EL EMENT, 'xmlstart', ''));

grdAttributes.Cells[0, 0] := 'Attribute name';
grdAttributes.Cells[1, 0] := 'Attribute value';
end;

procedure TfrmMain.LoadXML;
procedure EnterNode(const XMLNode: IXMLDOMNode; TreeNode: TTreeNode);
var
I: Integer;
XMLNodeList: IXMLDOMNodeList;
NewTreeNode: TTreeNode;
begin
NewTreeNode := trvStructure.Items.AddChild(TreeNode, XMLNode.nodeName);
NewTreeNode.Data := TXMLNodeWrapper.Create(XMLNode);
// use XMLNode.childNodes to get all nodes (incl. special types)
XMLNodeList := XMLNode.selectNodes('*');
for I := 0 to Pred(XMLNodeList.length) do
EnterNode(XMLNodeList.item[I], NewTreeNode);
end;
begin
for I := 0 to trvStructure.Items.Count - 1 do
TXMLNodeWrapper(trvStructure.Items.Item[I].Data).Destroy;
trvStructure.Items.BeginUpdate;
try
trvStructure.Items.Clear;
EnterNode(FDocument.documentElement, nil);
finally
trvStructure.Items.EndUpdate;
end;
end;

procedure TfrmMain.Open1Click(Sender: TObject);
begin
if OpenDialog1.Execute then
begin
FDocument.load(OpenDialog1.FileName);
FFileName := OpenDialog1.FileName;
LoadXML;
end;
end;

procedure TfrmMain.trvStructureChange(Sender: TObject; Node: TTreeNode);
var
I: Integer;
CurrentNode: IXMLDOMNode;
begin
CurrentNode := TXMLNodeWrapper(Node.Data).Node;
Caption := CurrentNode.nodeName;
if CurrentNode.selectNodes('*').length = 0 then
mmoNodeContent.Text := CurrentNode.text
else
mmoNodeContent.Text := '';
if CurrentNode.attributes.length 0 then
begin
grdAttributes.RowCount := Succ(CurrentNode.attributes.length);
grdAttributes.FixedRows := 1;
for I := 0 to Pred(CurrentNode.attributes.length) do
begin
grdAttributes.Cells[0, Succ(I)] := CurrentNode.attributes.item[I].nodeName;
grdAttributes.Cells[1, Succ(I)] := CurrentNode.attributes.item[I].text;
end;
end else begin
grdAttributes.RowCount := 2;
grdAttributes.Cells[0, 1] := '';
grdAttributes.Cells[1, 1] := '';
end;
end;

end.
man könnte die Namensfelder per Parser "korrigieren", falls das helfen könnte.

grüße
  Mit Zitat antworten Zitat
tofse

Registriert seit: 6. Jun 2011
Ort: Saarlouis
128 Beiträge
 
Delphi XE Professional
 
#7

AW: Probleme mit XML Encoding

  Alt 25. Jan 2018, 14:25
Habe es nun anders gelöst.
Lese erst die XML Datei in einer Variable FXMLContent und setze an den Anfang die Encoding Informationen.
Danach verwende ich
Xml.LoadFromXML(FXMLContent);
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
34.931 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#8

AW: Probleme mit XML Encoding

  Alt 25. Jan 2018, 14:50
Leider der gleiche Fehler
Das ist auch richtig so.

Xml.Encoding hat garnichts mit dem Einlesen zu tun.
Da steht das Encoding drin, was beim Auslesen der XML genutzt wurde, bzw. welches beim Speichern verwendet wird.

Erstmal ist diese XML nicht valide aka "ungültig", womit der Fehler völlig korrekt ist.
Es gilt das Encoding via BOM (für den ersten XML-Node), wenn kein BOM dann UTF-8. Und gibt es eine Processing Instruction (<?xml ...?> ), dann gilt nach ihr das darin definierte Encoding.
Als Ausnahme gelten UTF-16 LE und BE, welche auch ohne BOM am ersten < erkannt werden können. (#0'<' oder '<'#0)
Ohne Angabe eines Encoding sind XML immer UTF-8, also liegt der Fehler beim schreibenden Programm, wenn es ein falsches Encoding verwendet, als es (nicht) in der XML definiert hat.

Kann man beim LoadFromFile ein TEncoding-Parameter übergeben werden, um das Default-Encoding zu ändern?
Wenn nicht, dann mußt du die Datei selber einlesen, dabei das gewünschte TEncoding verwenden (bei normalen Textdateien ist es ANSI, unter Windows) und dann als String via LoadXML (oder wie das hieß) laden.
> Lesen mit TStringList oder Delphi-Referenz durchsuchenTFile.ReadAllText
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014

Geändert von himitsu (25. Jan 2018 um 14:56 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bernhard Geyer
Bernhard Geyer

Registriert seit: 13. Aug 2002
Ort: Oberreichenbach
16.455 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#9

AW: Probleme mit XML Encoding

  Alt 25. Jan 2018, 15:02
Zitat:
ein Fremdprogramm X exportiert XML Dateien.
Wenn die Datei so wie si angegeben ist aussieht, ist es kein gültiges XML.
Wenn du an diesem Fehler nix machen kannst (habe ich z.B. auch bei Adobe-SW die - sagen wir mal Adobe XML schreibt -), so solltest du evtl ein FixDefectXMLFromXYZ-Methode schreiben welche die Codierung korrekt setzt und den XML-Header ebenfalls ergänzt. Dann kannst du mit dem XML-Parser deiner Wahl nutzen.
Windows Vista - Eine neue Erfahrung in Fehlern.
  Mit Zitat antworten Zitat
Redeemer

Registriert seit: 19. Jan 2009
Ort: Kirchlinteln (LK Verden)
473 Beiträge
 
Delphi 2009 Professional
 
#10

AW: Probleme mit XML Encoding

  Alt 25. Jan 2018, 22:59
Was Bernhard meint, ist das hier:
Delphi-Quellcode:
var
  Stream1: TFileStream;
  Stream2: TMemoryStream;
const
  Head: AnsiString = '<?xml version="1.0" encoding="UTF-8"?>'; // oder Encoding Windows-1252
begin
  Stream1 := TFileStream.Create(DateiDatei, fmOpenRead or fmShareDenyNone);
  Stream2 := TMemoryStream.Create;
  try
    Stream2.Write(Head[1], Length(Head));
    Stream2.Copyfrom(Stream1, 0);
    Stream2.Position := 0;
    // bla
    Xml.LoadFromStream(Stream2);
    // bla
  finally
    Stream1.Free;
    Stream2.Free;
  end;
end;
Janni
2005 PE, 2009 PA, XE2 PA
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:22 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf