Ich erhalte ständig "XML-Parser-Fehler: Unterminiertes Attribut" mit meinem Parser, wenn ich versuche, HTML-Text oder CDATA innerhalb meines XML-Attributs einzufügen. Gibt es eine Möglichkeit, dies zu tun, oder ist dies nach dem Standard nicht zulässig?
Antworten
Zu viele Anzeigen?Nein, Die Markierung, die eine CDATA-Abschnitt ist als Wert eines Attributs nicht zulässig.
Nach der Spezifikation ist dieses Verbot eher indirekt als direkt. Die Spezifikation besagt, dass der Attributwert darf keine offene eckige Klammer haben . Offene eckige Klammern und kaufmännische Und-Zeichen müssen ausgeschnitten werden. Daher können Sie keinen CDATA-Abschnitt einfügen. womp womp.
Ein CData-Abschnitt wird nur interpretiert, wenn er sich in einem Textknoten eines Elements befindet.
Attribute können nur einfachen Text enthalten, keine Tags, Kommentare oder andere strukturierte Daten. Sie müssen alle Sonderzeichen durch die Verwendung von Zeicheneinheiten ausschließen. Zum Beispiel:
<code text="<a href="/">">
Damit würde die text
Attribut den Wert <a href="http://stackoverflow.com/">
. Beachten Sie, dass es sich hierbei nur um reinen Text handelt. Wenn Sie ihn also als HTML behandeln wollten, müssten Sie die Zeichenfolge selbst durch einen HTML-Parser laufen lassen. Das XML-DOM würde den String nicht analysieren. text
Attribut für Sie.
CDATA
ist hier leider eine zweideutige Aussage. Es gibt "CDATA-Abschnitte" et " CDATA
Attribut Typ" .
Ihr Attributwert kann vom Typ CDATA mit dem "CDATA-Attribut-Typ" sein.
Hier ist eine xml-Datei, die eine "CDATA-Abschnitt" ( alias. CDSect
):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<elemke>
<![CDATA[
foo
]]>
</elemke>
Hier ist eine xml-Datei, die eine "CDATA-Attribut Typ" (als AttType
):
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE elemke [
<!ATTLIST brush wood CDATA #REQUIRED>
]>
<elemke>
<brush wood="guy
threep"/>
</elemke>
Sie kann nicht verwenden eine "CDATA-Abschnitt" für ein Attribut Wert: falsch: <brush wood=<![CDATA[foo]]>/>
Sie kann verwenden eine "CDATA-Attribut Typ" für den Typ Ihres Attributs, denke ich, dass dies im Normalfall tatsächlich geschieht, und Ihr Attributwert es eigentlich ein CDATA: für ein Element wie <brush wood="guy
threep"/>
in dem rohen binären Bytestring, der die .xml
Datei, haben Sie guy
threep
Wenn die Datei jedoch verarbeitet wird, wird der Attributwert im Speicher wird sein
guy
threep
Ihr Problem könnte darin liegen, 1) eine richtige Xml-Datei zu erzeugen und 2) einen "Xml-Prozessor" so zu konfigurieren, dass er die gewünschte Ausgabe erzeugt.
Zum Beispiel, für den Fall, dass Sie von Hand eine rohe Binärdatei als Xml-Datei schreiben müssen Sie diese Escapes in den Attributwertteil in der Rohdatei einfügen, wie ich es geschrieben habe <brush wood="guy
threep"/>
hier, anstelle von <brush wood="guy
(Zeilenumbruch) threep"/>
Dann das Parsen würde tatsächlich einen Zeilenumbruch ergeben, ich habe das mit einem Prozessor ausprobiert.
Sie können es mit einem Prozessor wie Saxon probieren oder als Arme-Leute-Experiment mit einem Browser, indem Sie die xml-Datei in Firefox öffnen und Kopieren des Wertes in einen Texteditor - firefox angezeigt den Zeilenumbruch als Leerzeichen, aber beim Kopieren der Zeichenkette in einen Texteditor wurde der Zeilenumbruch angezeigt. (Mit einem besser geeigneten Prozessor könnten Sie die direkte Ausgabe wahrscheinlich sofort speichern).
Jetzt müssen Sie "nur" noch dafür sorgen, dass Sie dieses CDATA angemessen behandeln. Wenn Sie z. B. ein XSL-Stylesheet haben, das eine HTML-Datei erzeugt, können Sie etwas wie Folgendes verwenden .xsl
für ein solches xml:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="split">
<xsl:param name="list" select="''" />
<xsl:param name="separator" select="'
'" />
<xsl:if test="not($list = '' or $separator = '')">
<xsl:variable name="head" select="substring-before(concat($list, $separator), $separator)" />
<xsl:variable name="tail" select="substring-after($list, $separator)" />
<xsl:value-of select="$head"/>
<br/><xsl:text>
</xsl:text>
<xsl:call-template name="split">
<xsl:with-param name="list" select="$tail" />
<xsl:with-param name="separator" select="$separator" />
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="brush">
<html>
<xsl:call-template name="split">
<xsl:with-param name="list" select="@wood"/>
</xsl:call-template>
</html>
</xsl:template>
</xsl:stylesheet>
Die in einem Browser oder mit einem Prozessor wie saxon mit java -jar saxon9he.jar -s:eg2.xml -xsl:eg2.xsl -o:eg2.html
saxon home edition 9.5 würde dieses html-ähnliche Ding erzeugen:
<html>guy<br>
threep<br>
</html>
die in einem Browser wie folgt aussehen wird:
guy
threep
Hier verwende ich eine rekursive Vorlage 'split'. von Tomalak Dank an Mads Hansen weil mein Zielprozessor beides nicht unterstützt string-join
noch tokenize
die nur der Version 2.0 entsprechen.
Handelt es sich bei einem Attribut nicht um einen tokenisierten oder enumerierten Typ, wird es als CDATA verarbeitet. Die Einzelheiten zur Verarbeitung des Attributs finden Sie in der Extensible Markup Language (XML) 1.0 (Fünfte Ausgabe) .
Es gibt drei Arten von XML-Attributtypen: einen Stringtyp, eine Reihe von tokenisierten Typen und aufgezählte Typen. Der Stringtyp kann eine beliebige Zeichenkette als Wert annehmen; die tokenisierten Typen sind stärker eingeschränkt. Die in der Grammatik vermerkten Gültigkeitseinschränkungen werden angewendet, nachdem der Attributwert normalisiert wurde, wie in 3.3.3 Normalisierung von Attributwerten beschrieben.
[54] AttType ::= StringType | TokenizedType | EnumeratedType [55] StringType ::= 'CDATA' [56] TokenizedType ::= 'ID' [VC: ID] [VC: One ID per Element Type] [VC: ID Attribute Default] | 'IDREF' [VC: IDREF] | 'IDREFS' [VC: IDREF] | 'ENTITY' [VC: Entity Name] | 'ENTITIES' [VC: Entity Name] | 'NMTOKEN' [VC: Name Token] | 'NMTOKENS' [VC: Name Token]
...
3.3.3 Normalisierung von Attribut-Werten
Bevor der Wert eines Attributs an die Anwendung weitergegeben oder auf Gültigkeit geprüft wird, MUSS der XML-Prozessor den Attributwert normalisieren, indem er den nachstehenden Algorithmus anwendet oder eine andere Methode einsetzt, so dass der an die Anwendung weitergegebene Wert mit dem durch den Algorithmus erzeugten Wert identisch ist.
- Alle Zeilenumbrüche MÜSSEN bei der Eingabe in #xA normalisiert worden sein, wie in 2.11 End-of-Line-Behandlung Der Rest des Algorithmus arbeitet also mit auf diese Weise normalisiertem Text.
- Beginnen Sie mit einem normalisierten Wert, der aus einer leeren Zeichenkette besteht.
- Führen Sie für jedes Zeichen, jede Entitätsreferenz oder jede Zeichenreferenz im nicht normalisierten Attributwert, beginnend mit dem ersten und fortfahrend bis zum letzten, Folgendes aus:
- Bei einer Zeichenreferenz wird das referenzierte Zeichen an den normalisierten Wert angehängt.
- Für eine Entitätsreferenz wenden Sie Schritt 3 dieses Algorithmus rekursiv auf den Ersatztext der Entität an.
- Für ein Leerzeichen (#x20, #xD, #xA, #x9) wird ein Leerzeichen (#x20) an den normalisierten Wert angehängt.
- Bei einem anderen Zeichen wird das Zeichen an den normalisierten Wert angehängt.
Wenn der Attributtyp nicht CDATA ist, MUSS der XML-Prozessor den normalisierten Attributwert weiterverarbeiten, indem er alle führenden und nachfolgenden Leerzeichen (#x20) verwirft und Folgen von Leerzeichen (#x20) durch ein einzelnes Leerzeichen (#x20) ersetzt.
Enthält der nicht normalisierte Attributwert einen Zeichenverweis auf ein Leerzeichen, das kein Leerzeichen ist (#x20), enthält der normalisierte Wert das referenzierte Zeichen selbst (#xD, #xA oder #x9). Dies steht im Gegensatz zu dem Fall, in dem der nicht normalisierte Wert ein Leerzeichen (keine Referenz) enthält, das im normalisierten Wert durch ein Leerzeichen (#x20) ersetzt wird, und steht auch im Gegensatz zu dem Fall, in dem der nicht normalisierte Wert eine Entitätsreferenz enthält, deren Ersetzungstext ein Leerzeichen enthält; da dieser rekursiv verarbeitet wird, wird das Leerzeichen im normalisierten Wert durch ein Leerzeichen (#x20) ersetzt.
Alle Attribute, für die keine Deklaration gelesen wurde, SOLLTEN von einem nicht-validierenden Prozessor so behandelt werden, als ob sie deklariert wären CDATA .
Es ist ein Fehler, wenn ein Attributwert enthält eine Referenz zu einer Entität, für die keine Erklärung gelesen wurde.
- See previous answers
- Weitere Antworten anzeigen