Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Problem mit regulärem Ausdruck (https://www.delphipraxis.net/206193-problem-mit-regulaerem-ausdruck.html)

Peter666 28. Nov 2020 11:36

Problem mit regulärem Ausdruck
 
Hallo in die Runde,

ich möchte etwaige Fehler in XMLs beheben, bevor ich diese in dem Parser lade.

Delphi-Quellcode:
function CleanInvalidXmlChars(const AText: String): String;
var RegexObj: TRegExpr;
begin
  RegexObj := TRegExpr.Create;
  try
    RegexObj.Expression :=
    '[\xC0-\xC1] # Invalid UTF-8 Bytes '+
    '| [\xF5-\xFF] # Invalid UTF-8 Bytes '+
    '| [\xE0[\x80-\x9F] # Overlong encoding of prior code point'+
    '| [\xF0[\x80-\x8F] # Overlong encoding of prior code point'+
    '| [\xC2-\xDF][?![\x80-\xBF]] # Invalid UTF-8 Sequence Start'+
    '| [\xE0-\xEF][?![\x80-\xBF]{2}] # Invalid UTF-8 Sequence Start'+
    '| [\xF0-\xF4][?![\x80-\xBF]{3}] # Invalid UTF-8 Sequence Start'+
    '| [?<=[\x00-\x7F\xF5-\xFF]][\x80-\xBF] # Invalid UTF-8 Sequence Middle'+
    '| [?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]|[\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2}][\x80-\xBF]] # Overlong Sequence'+
    '| [?<=[\xE0-\xEF]][\x80-\xBF][?![\x80-\xBF]] # Short 3 byte sequence'+
    '| [?<=[\xF0-\xF4]][\x80-\xBF][?![\x80-\xBF]{2}] # Short 4 byte sequence'+
    '| [?<=[\xF0-\xF4][\x80-\xBF]][\x80-\xBF][?![\x80-\xBF]] # Short 4 byte sequence (2)';
    result := RegexObj.Replace(AText, '', true);
  finally
    RegExObj.Free;
  end;
end;
Dazu nutze ich folgenden Ausdruck.
Die Quelle für den String ist folgende: https://www.ryadel.com/en/php-skip-i...l-file-string/

Leider meckert die Regexp Bibliothek dass der "Modifier urecognized" ist. Für mich sind reguläre Ausdrücke so etwas wie böhmische Dörfer. Hat jemand vielleicht eine Idee was da falsch ist?

Peter

himitsu 28. Nov 2020 16:12

AW: Problem mit regulärem Ausdruck
 
Erstmal kommt es drauf an, wass für eine Implementation der Regulären Ausdrücke du hast,
denn da unterscheiden sich einige Dinge Grundlegend, bzw. einige Sachen sind nicht überall möglich.

z.B. die Kommentare im RegEx.
Delphi-Quellcode:
#...
wird hier nicht unterstützt, sondern
Delphi-Quellcode:
(?#...)

und selbst wenn # als Kommentar ginge, dann fehlt dahinter der Zeilenumbruch (#10, #13#10, bzw. sLineBreak) als Ende des Kommentars, was in deinem "einen" String nicht enthalten ist.
https://regex.sorokin.engineer/de/la....html#comments
Aber hier kanns die Kommentare ja auch einfach ins Pascal/Delphi hier \\ verschieben.
Delphi kennt leider keine MultiLine-Strings, da muß man die Zeilenumbrüche eben selbst machen.

Und dann wird bei einigen Libs mit einem Start-/Ende-Zeichen gearbeitet und dahinter in den RegEx die Modifier.
Wie bei deiner Vorlage
Delphi-Quellcode:
/.../x
, während Andere das nicht haben (z.B. TRegEx im Delphi), wo die Modifier als Enum in einem eigenen Parameter übergeben werden.
Da hier "Modifier urecognized" als Fehler kommt, müsste für dein TRegExpr in den RegEx-String also sowas mit rein. (in die "neue" Delphi-Implementation Delphi-Referenz durchsuchenTRegEx aber nicht)

Auch Leerzeichen/Zeilenumbrüche, da kommt es auf die Konfiguration/Modifierer drauf an, ob sie "ignoriert" oder als "Suchstring" mit behandelt werden.
In den Delphiimplementationen ist eigentlich Letzteres meistens der Standardfall, außer man gibt den entsprechenden Modifier an.
Hier ist es der Modifier
Delphi-Quellcode:
x
(eXtended).

CHackbart 28. Nov 2020 20:49

AW: Problem mit regulärem Ausdruck
 
Ich habe dein Skript mal angepasst, aber ich kenne mich mit RegExp auch nicht aus.

Delphi-Quellcode:
function CleanInvalidXmlChars(const AText: string): string;
//https://www.ryadel.com/en/php-skip-invalid-characters-utf-8-xml-file-string/
var
  RegexObj: TRegExpr;
begin
  RegexObj := TRegExpr.Create;
  try
    RegexObj.Expression :=
      '[\xC0-\xC1] # Invalid UTF-8 Bytes ' + sLineBreak +
      '| [\xF5-\xFF] # Invalid UTF-8 Bytes ' + sLineBreak +
      '| [\xE0[\x80-\x9F] # Overlong encoding of prior code point' + sLineBreak +
      '| [\xF0[\x80-\x8F] # Overlong encoding of prior code point' + sLineBreak +
      '| [\xC2-\xDF][?![\x80-\xBF]] # Invalid UTF-8 Sequence Start' + sLineBreak +
      '| [\xE0-\xEF][?![\x80-\xBF]{2}] # Invalid UTF-8 Sequence Start' + sLineBreak +
      '| [\xF0-\xF4][?![\x80-\xBF]{3}] # Invalid UTF-8 Sequence Start' + sLineBreak +
      '| [?<=[\x00-\x7F\xF5-\xFF]][\x80-\xBF] # Invalid UTF-8 Sequence Middle' + sLineBreak +
   // '| [?<![\xC2-\xDF]|[\xE0-\xEF]|[\xE0-\xEF][\x80-\xBF]|[\xF0-\xF4]|[\xF0-\xF4][\x80-\xBF]|[\xF0-\xF4][\x80-\xBF]{2}][\x80-\xBF] # Overlong Sequence' + sLineBreak +
      '| [?<=[\xE0-\xEF]][\x80-\xBF][?![\x80-\xBF]] # Short 3 byte sequence' + sLineBreak +
      '| [?<=[\xF0-\xF4]][\x80-\xBF][?![\x80-\xBF]{2}] # Short 4 byte sequence' + sLineBreak +
      '| [?<=[\xF0-\xF4][\x80-\xBF]][\x80-\xBF][?![\x80-\xBF]] # Short 4 byte sequence (2)';
    Result := RegexObj.Replace(AText, '', True);
  finally
    RegExObj.Free;
  end;
end;
Die eine Zeile musste ich entfernen, da sonst das Skript bei meinem Beispiel-XML einfach bei den Elementen das < entfernt hat:

Code:
<?xml version="1.0" encoding="UTF-8"?>
<Content xmlns="tag:atsc.org,2016:XMLSchemas/ATSC3/SA/1.0/"
         id="bcast://trivenidigital.com/Content961747"
         version="4">
   <ServiceReference idRef="bcast://trivenidigital.com/Service149"/>
   <Name text="Como dice el dicho"/>
   <Description text="Cada historia da inicio cuando la primera parte del dicho es escrita en una de las paredes del café, sea por Tomás, sea por Isabel, o por algún cliente."/>
   <ContentAdvisoryRatings>
      <RegionIdentifier>1</RegionIdentifier>
      <RatingDescription>TV-14</RatingDescription>
      <RatingDimensions>1</RatingDimensions>
      <RatingDimVal>
         <RatingDimension>0</RatingDimension>
         <RatingValueString>TV-14</RatingValueString>
      </RatingDimVal>
   </ContentAdvisoryRatings>
   <PrivateExt>
      <Components>
         <AudioComponent xml:lang="spa">Unspecified</AudioComponent>
      </Components>
   </PrivateExt>
</Content>
Ob das jetzt richtig funktioniert, weiß ich auch nicht wirklich, aber die RegExpr Klasse meckert zumindest nicht.
Ich gebe Himitsu Recht, Linebreaks müssen da rein, sonst sollte ab dem ersten Kommentar eigentlich alles dahinter liegende deaktiviert sein. Ist es zumindest in der bei Lazarus beiliegenden Regexpr Version aber kurioserweise nicht.

Christian


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:31 Uhr.

Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf