3 Stimmen

Welche Strategien gibt es, um aus Zeichenentitäten zu entkommen?

Wir verarbeiten eine Reihe englischsprachiger Dokumente (hauptsächlich wissenschaftliche) und stoßen dabei auf Probleme bei der Übertragung von Nicht-ANSI-Zeichen durch die verschiedenen Komponenten. Die Dokumente können "ASCII", UNICODE, PDF oder HTML sein. Wir können zum jetzigen Zeitpunkt nicht vorhersagen, welche Werkzeuge in unserer Kette sein werden oder ob sie andere Zeichenkodierungen als ANSI zulassen werden. Selbst in UNICODE ausgedrückte lateinische ISO-Zeichen werden Probleme bereiten (z. B. werden sie in Browsern falsch angezeigt). Wir werden wahrscheinlich auf eine Reihe von Symbolen stoßen, darunter auch mathematische und griechische. Wir möchten diese in eine Textzeichenfolge "umwandeln", die eine mehrstufige Verarbeitung (einschließlich XML und Regex-Tools) übersteht, und sie dann möglicherweise im letzten Schritt wieder zusammensetzen (obwohl wir uns eher mit der Semantik als mit der Typografie befassen, so dass dies ein geringeres Problem darstellt).

Ich schätze, dass es keine absolute Antwort gibt - jedes Escaping kann in einigen Fällen kollidieren - aber ich bin auf der Suche nach etwas in der Nähe der Linien von XML <![CDATA[ ...]]> die die meisten nicht-rekursiven XML-Operationen übersteht. Zeichen wie [ sind schlecht, da sie in Regexen üblich sind. Ich frage mich also, ob es einen allgemein akzeptierten Ansatz gibt, anstatt unseren eigenen zu erfinden.

Ein typisches Beispiel ist das Symbol "Grad":

HTML Entity (decimal)   &#176;
HTML Entity (hex)   &#xb0;
HTML Entity (named)     &deg;
How to type in Microsoft Windows    Alt +00B0
Alt 0176
Alt 248
UTF-8 (hex)     0xC2 0xB0 (c2b0)
UTF-8 (binary)  11000010:10110000
UTF-16 (hex)    0x00B0 (00b0)
UTF-16 (decimal)    176
UTF-32 (hex)    0x000000B0 (00b0)
UTF-32 (decimal)    176
C/C++/Java source code  "\u00B0"
Python source code  u"\u00B0"

Wahrscheinlich werden wir auch auf TeX

$10\,^{\circ}{\rm C}$

ou

\degree

daher sind Backslashes, Curlies und Dollars eine schlechte Idee.

Wir könnten zum Beispiel Markierungen wie diese verwenden:

__deg__
__#176__

und das wird wahrscheinlich funktionieren, aber ich wäre dankbar für Ratschläge von denen, die ähnliche Probleme haben.

Update Ich akzeptiere die Forderung von @MichaelB, dass wir durchgehend UTF-8 verwenden. Ich mache mir Sorgen, dass einige unserer Tools nicht konform sind, und wenn das der Fall ist, werde ich das noch einmal überdenken. Beachten Sie, dass meine ursprüngliche Frage nicht gut formuliert ist - lesen Sie seine Antwort und den darin enthaltenen Link.

4voto

Michael Borgwardt Punkte 334642
  • Beauftragen Sie jemanden, der sich wirklich mit Zeichenkodierungen auskennt. Es sieht so aus, als ob Sie das nicht tun, weil Sie die Terminologie nicht richtig verwenden. Alternativ dazu, dies lesen .
  • Erfinden Sie nicht Ihr eigenes Fluchtprogramm - es wird Ihnen mehr Probleme bereiten, als es lösen wird. Stattdessen, Normalisierung der verschiedenen Quellkodierungen auf UTF-8 (was eigentlich nur ein solches Escape-Schema ist, nur effizienter und standardisierter) und die korrekte Handhabung von Zeichenkodierungen. Vielleicht verwenden Sie UTF-7, wenn Sie wirklich so viel Angst vor hohen Bits haben.
  • In der heutigen Zeit ist es nicht akzeptabel, wenn Zeichenkodierungen nicht korrekt verarbeitet werden. Wenn ein Tool dies nicht tut, sollten Sie es aufgeben - es ist höchstwahrscheinlich auch in vielerlei anderer Hinsicht ein Code von sehr schlechter Qualität und den Aufwand nicht wert.

1voto

Stefano Borini Punkte 132313

Vielleicht verstehe ich das Problem nicht richtig, aber ich würde eine sehr eindeutige Escape-Markierung erstellen, die wahrscheinlich nicht berührt wird, und sie dann verwenden, um die Entität als base32-String zu kodieren.

Schließlich können Sie die eindeutigen Marker und ihre Anzahl entlang der Kette über einen separaten Kanal übertragen und ihr Vorhandensein und ihre Anzahl am Ende überprüfen.

Beispiel, etwas wie

the value of the temperature was 18 cd48d8c50d7f40aeb6a164181b17feee EZSGKZY= cd48d8c50d7f40aeb6a164181b17feee

Ihre Markierung ist eine uuid, und die Entität ist &deg in base32 kodiert. Sie geben dann die Markierung cd48d8c50d7f40aeb6a164181b17feee weiter. Sie kann nicht beschädigt werden (wenn sie beschädigt wird, werden Ihre Filter wahrscheinlich sowieso alles beschädigen, was aus Buchstaben und Zahlen besteht, aber zumindest können Sie sie ausschließen, weil sie eine feste Länge haben), und Sie können den Inhalt immer wiederherstellen, indem Sie innerhalb der beiden Markierungen suchen.

Wenn Sie uuids in Ihren Dokumenten haben, könnte dies natürlich ein Problem darstellen, aber da Sie sie nicht als autorisierte Markierungen über den lateralen Kanal übertragen, werden sie nicht als solche erkannt (und in jedem Fall wird das, was dazwischen liegt, sowieso nicht als base32-String validiert).

Wenn Sie nach ihnen suchen müssen, können Sie die uuid-Unterteilung beibehalten und dann eine geeignete Regexp verwenden, um diese Vorkommen zu erkennen. Beispiel:

>>> re.search("(\w{8}-\w{4}-\w{4}-\w{4}-\w{12})(.*?)(\\1)", s)
<_sre.SRE_Match object at 0x1003d31f8>
>>> _.groups()
('6d378205-1265-44e4-80b8-a47d1ceaad51', ' EZSGKZY= ', '6d378205-1265-44e4-80b8-a47d1ceaad51')
>>> 

Wenn Sie wirklich ein bestimmtes "Token" zum Testen benötigen, können Sie eine uuid1 mit einer genau definierten Spezifikation eines Knotens verwenden:

>>> uuid.uuid1(node=0x1234567890)  
UUID('bdcce554-e95d-11de-bd0f-001234567890')
>>> uuid.uuid1(node=0x1234567890)  
UUID('c4c57a91-e95d-11de-90ca-001234567890')
>>> 

Sie können jeden beliebigen Knoten verwenden, die uuid wird eindeutig sein, aber Sie können trotzdem auf Vorhandensein testen (obwohl es zu falsch positiven Ergebnissen kommen kann).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X