+ Antworten
Ergebnis 1 bis 4 von 4

Thema: Probleme mit Auszeichnungen in einem Textbereich

  1. #1
    User Halbes Megabyte Themenstarter
    Avatar von Crian
    Registriert seit
    02.08.2013
    Fachbeiträge
    542
    Genannt
    31 Post(s)
    Ich bekomme von einem Kollegen eine XML-Datei, die mich vor ein unerwartetes Problem stellt. Die XML-Dateien, die ich bisher verwendet hatte, hatten als Inhalt von Tags entweder nur Text, oder andere Tags. Aber keine Mischform. Also etwa so:

    Code:
    <dinge>
        <information>huhu</information>
        <zeugs>
            <zeug>A</zeug>
            <zeug>B</zeug>
        </zeugs>
    </dinge>
    Nun aber sieht ein Exemplar dieser Dateien so aus:

    Code:
    <dinge>
        <information>huhu<oha>ueberraschung!</oha></information>
    </dinge>
    Das wird wohl kaum den XML-Regeln widersprechen, immerhin gibt es sowas in HTML ja auch:

    Code:
    <p>Dies ist ein Satz mit einem <b>fettgeschriebenem</b> Wort.</p>
    Ich weiß nur nicht so genau, wie ich dies nun parsen soll. Ich hab mal ein KKSB (oder wie sich das noch gleich abkürzte) geschrieben:

    Java Code:
    1. package xml;
    2.  
    3. import java.io.Reader;
    4. import java.io.StringReader;
    5.  
    6. import javax.xml.stream.XMLInputFactory;
    7. import javax.xml.stream.XMLStreamConstants;
    8. import javax.xml.stream.XMLStreamException;
    9. import javax.xml.stream.XMLStreamReader;
    10.  
    11. public class XmlProblemDemonstration {
    12.  
    13.     public class XmlInfo {
    14.         private String information;
    15.  
    16.         public String getInformation() {
    17.             return information;
    18.         }
    19.  
    20.         void setInformation(String information) {
    21.             this.information = information;
    22.         }
    23.  
    24.         @Override
    25.         public String toString() {
    26.             return "XmlInfo [information=" + information + "]";
    27.         }
    28.     }
    29.  
    30.     public XmlInfo work(String input) {
    31.         XmlInfo xmlInfo = null;
    32.         try {
    33.             xmlInfo = tryToRead(input);
    34.         } catch (XMLStreamException exception) {
    35.             exception.printStackTrace();
    36.         }
    37.         return xmlInfo;
    38.     }
    39.  
    40.     private XmlInfo tryToRead(String input) throws XMLStreamException {
    41.         Reader reader = new StringReader(input);
    42.         XMLInputFactory factory = XMLInputFactory.newInstance();
    43.         XMLStreamReader parser = factory.createXMLStreamReader(reader);
    44.  
    45.         XmlInfo xmlInfo = new XmlInfo();
    46.  
    47.         while (parser.hasNext()) {
    48.             parser.next();
    49.             switch (parser.getEventType()) {
    50.                 case XMLStreamConstants.START_ELEMENT:
    51.                     switch (parser.getLocalName()) {
    52.                         case "information": {
    53.                             String information = parser.getElementText();
    54.                             //String information = parser.getText();
    55.                             xmlInfo.setInformation(information);
    56.                             break;
    57.                         }
    58.                     }
    59.                     break;
    60.             }
    61.         }
    62.         return xmlInfo;
    63.     }
    64.  
    65.     public static void main(String[] args) {
    66.         XmlProblemDemonstration demo = new XmlProblemDemonstration();
    67.         for (String input : new String[] {
    68.                 "<dinge><information>foo</information></dinge>",
    69.                 "<dinge><information>bar</information></dinge>",
    70.                 "<dinge><information>baz<oha>ueberraschung!</oha></information></dinge>"
    71.                 }) {
    72.             System.out.println("Eingabe: " + input);
    73.             XmlInfo info = demo.work(input);
    74.             if (null == info) {
    75.                 System.out.println("Fehler in der Verarbeitung!");
    76.             }
    77.             else {
    78.                 System.out.println("Ergebnis: " + info);
    79.             }
    80.             System.out.println();
    81.         }
    82.     }
    83.  
    84. }

    Die Ausgabe ist:

    Code:
    Eingabe: <dinge><information>foo</information></dinge>
    Ergebnis: XmlInfo [information=foo]
    
    Eingabe: <dinge><information>bar</information></dinge>
    Ergebnis: XmlInfo [information=bar]
    
    Eingabe: <dinge><information>baz<oha>ueberraschung!</oha></information></dinge>
    javax.xml.stream.XMLStreamException: ParseError at [row,col]:[1,29]
    Message: elementGetText() function expects text only elment but START_ELEMENT was encountered.
    	at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.getElementText(Unknown Source)
    	at xml.XmlProblemDemonstration.tryToRead(XmlProblemDemonstration.java:53)
    	at xml.XmlProblemDemonstration.work(XmlProblemDemonstration.java:33)
    	at xml.XmlProblemDemonstration.main(XmlProblemDemonstration.java:73)
    Fehler in der Verarbeitung!
    Gefunden habe ich schon: http://stackoverflow.com/questions/1...-start-element

    Aber wenn ich die auskommentierte Zeile mit getText statt der mit getElementText verwende, bekomme ich den folgenden Fehler:

    Code:
    Eingabe: <dinge><information>foo</information></dinge>
    Exception in thread "main" java.lang.IllegalStateException: Current state START_ELEMENT is not among the statesCHARACTERS, COMMENT, CDATA, SPACE, ENTITY_REFERENCE, DTD valid for getText() 
    	at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.getText(Unknown Source)
    	at xml.XmlProblemDemonstration.tryToRead(XmlProblemDemonstration.java:54)
    	at xml.XmlProblemDemonstration.work(XmlProblemDemonstration.java:33)
    	at xml.XmlProblemDemonstration.main(XmlProblemDemonstration.java:73)

    Vermutlich nur ein Knoten in den Gedanken. Kann mich jemand in die richtige Richtung stupsen?

    Ich könnte natürlich damit anfangen, diese Xml-Datei mit regulären Ausdrücken zu bearbeiten, aber eigentlich ist das ja der deutlich weniger elegante Weg, und wenn sich eine Parser-Lösung bietet, wäre das vorzuziehen.
    Geändert von Crian (22.03.2014 um 12:14 Uhr)

  2. #2
    User Halbes Megabyte Themenstarter
    Avatar von Crian
    Registriert seit
    02.08.2013
    Fachbeiträge
    542
    Genannt
    31 Post(s)
    Inzwischen habe ich mit einem Freund zusammen folgende Lösung gefunden. Wie schön das ganze ist, steht auf einem anderen Blatt, aber so "funktioniert" es zumindest, alle mich interessierenden Informationen aus der XML-Datei zu extrahieren.

    Java Code:
    1. package xml;
    2.  
    3. import java.io.Reader;
    4. import java.io.StringReader;
    5. import java.util.HashMap;
    6. import java.util.Map;
    7.  
    8. import javax.xml.stream.FactoryConfigurationError;
    9. import javax.xml.stream.XMLInputFactory;
    10. import javax.xml.stream.XMLStreamConstants;
    11. import javax.xml.stream.XMLStreamException;
    12. import javax.xml.stream.XMLStreamReader;
    13.  
    14. public class XmlProblemDemonstration2 {
    15.  
    16.     public class XmlInfo {
    17.         private String information;
    18.         private Map<String, String> informationParts;
    19.  
    20.         public String getInformation() {
    21.             return information;
    22.         }
    23.  
    24.         public Map<String, String> getInformationParts() {
    25.             return informationParts;
    26.         }
    27.  
    28.         void setInformationParts(Map<String, String> informationParts) {
    29.             this.informationParts = informationParts;
    30.         }
    31.  
    32.         void setInformation(String information) {
    33.             this.information = information;
    34.         }
    35.  
    36.         @Override
    37.         public String toString() {
    38.             return "XmlInfo [information=" + information
    39.                     + ", informationParts=" + informationParts + "]";
    40.         }
    41.     }
    42.  
    43.     public XmlInfo work(String input) {
    44.         XmlInfo xmlInfo = null;
    45.         try {
    46.             xmlInfo = tryToRead(input);
    47.         }
    48.         catch (XMLStreamException exception) {
    49.             exception.printStackTrace();
    50.         }
    51.         catch (FactoryConfigurationError error) {
    52.             error.printStackTrace();
    53.         }
    54.         return xmlInfo;
    55.     }
    56.  
    57.     private XmlInfo tryToRead(String input) throws FactoryConfigurationError,
    58.             XMLStreamException {
    59.         XMLStreamReader parser = openXmlParser(input);
    60.         XmlInfo xmlInfo = new XmlInfo();
    61.  
    62.         /* Das zuletzt geöffnete Elemente. */
    63.         String element = null;
    64.  
    65.         /* Gibt an, ob information offen ist. */
    66.         boolean informationIsOpen = false;
    67.  
    68.         /*
    69.          * Verzeichnis der anderen Unter-Informationen, die zu "information"
    70.          * gehören.
    71.          */
    72.         Map<String, String> informationParts = null;
    73.  
    74.         while (parser.hasNext()) {
    75.             parser.next();
    76.             switch (parser.getEventType()) {
    77.                 case XMLStreamConstants.START_ELEMENT:
    78.                     /* Wir merken uns, welches Element zuletzt geöffnet wurde: */
    79.                     element = parser.getLocalName();
    80.                     //System.out.println("Öffnendes Element: " + element);
    81.  
    82.                     /*
    83.                      * Falls sich information öffnet, merken wir uns, dass
    84.                      * dieses Element geöffnet ist und initialisieren das
    85.                      * Verzeichnis der anderen zur Information gehörenden Werte:
    86.                      */
    87.                     if ("information".equals(element)) {
    88.                         informationIsOpen = true;
    89.                         informationParts = new HashMap<>();
    90.                     }
    91.                     break;
    92.                 case XMLStreamConstants.END_ELEMENT:
    93.                     switch (parser.getLocalName()) {
    94.                         case "information": {
    95.                             informationIsOpen = false;
    96.                             xmlInfo.setInformationParts(informationParts);
    97.                         }
    98.                     }
    99.                     break;
    100.                 case XMLStreamConstants.CDATA:
    101.                     //System.out.println("CDATA: " + parser.getText());
    102.                     break;
    103.                 case XMLStreamConstants.SPACE:
    104.                     //System.out.println("SPACE: " + parser.getText());
    105.                     break;
    106.                 case XMLStreamConstants.CHARACTERS:
    107.                     String characters = parser.getText();
    108.                     //System.out.println("CHARACTERS: " + characters);
    109.  
    110.                     /*
    111.                      * Wenn "information" geöffnet ist, aber nicht zuletzt
    112.                      * "information" geöffnet wurde, sondern ein anderes
    113.                      * Element, sichern wir dieses:
    114.                      */
    115.                     if (informationIsOpen && !"information".equals(element)) {
    116.                         informationParts.put(element, characters);
    117.                         /*
    118.                          * Falls das letzte öffnende Element information war,
    119.                          * die Information sichern:
    120.                          */
    121.                         if ("information".equals(element)) {
    122.                             xmlInfo.setInformation(characters);
    123.                         }
    124.                     }
    125.                     break;
    126.             }
    127.         }
    128.         return xmlInfo;
    129.     }
    130.  
    131.     private XMLStreamReader openXmlParser(String input)
    132.             throws FactoryConfigurationError, XMLStreamException {
    133.         Reader reader = new StringReader(input);
    134.         XMLInputFactory factory = XMLInputFactory.newInstance();
    135.         XMLStreamReader parser = factory.createXMLStreamReader(reader);
    136.         return parser;
    137.     }
    138.  
    139.     public static void main(String[] args) {
    140.         XmlProblemDemonstration2 demo = new XmlProblemDemonstration2();
    141.         for (String input : new String[] {
    142.                 "<dinge><information>foo</information></dinge>",
    143.                 "<dinge><information>bar</information></dinge>",
    144.                 "<dinge><information>baz<oha>ueberraschung!</oha></information></dinge>"
    145.                 }) {
    146.             System.out.println("Eingabe: " + input);
    147.             XmlInfo info = demo.work(input);
    148.             if (null == info) {
    149.                 System.out.println("Fehler in der Verarbeitung!");
    150.             }
    151.             else {
    152.                 System.out.println("Ergebnis: " + info);
    153.             }
    154.             System.out.println();
    155.         }
    156.     }
    157.  
    158. }

    Ausgabe:

    Code:
    Eingabe: <dinge><information>foo</information></dinge>
    Ergebnis: XmlInfo [information=null, informationParts={}]
    
    Eingabe: <dinge><information>bar</information></dinge>
    Ergebnis: XmlInfo [information=null, informationParts={}]
    
    Eingabe: <dinge><information>baz<oha>ueberraschung!</oha></information></dinge>
    Ergebnis: XmlInfo [information=null, informationParts={oha=ueberraschung!}]
    Vermutlich ist für mein eigentliches Problem keine Map die Lösung, sondern eine Liste solcher String-Paare, damit nicht zwei "oha"-Elemente einander überschrieben.

    *** Edit ***

    Falls es interessiert, die Lösung sieht dann so aus:

    Java Code:
    1. package xml;
    2.  
    3. import java.io.Reader;
    4. import java.io.StringReader;
    5. import java.util.ArrayList;
    6. import java.util.List;
    7.  
    8. import javax.xml.stream.FactoryConfigurationError;
    9. import javax.xml.stream.XMLInputFactory;
    10. import javax.xml.stream.XMLStreamConstants;
    11. import javax.xml.stream.XMLStreamException;
    12. import javax.xml.stream.XMLStreamReader;
    13.  
    14. public class XmlProblemDemonstration3 {
    15.  
    16.     public class ElementData {
    17.         private final String element;
    18.         private final String data;
    19.         public ElementData(String element, String data) {
    20.             this.element = element;
    21.             this.data = data;
    22.         }
    23.         public String getElement() {
    24.             return element;
    25.         }
    26.         public String getData() {
    27.             return data;
    28.         }
    29.         @Override
    30.         public String toString() {
    31.             return "ElementData [element=" + element + ", data=" + data + "]";
    32.         }
    33.     }
    34.  
    35.     public class XmlInfo {
    36.         private String information;
    37.         private List<ElementData> informationParts;
    38.  
    39.         public String getInformation() {
    40.             return information;
    41.         }
    42.  
    43.         public List<ElementData> getInformationParts() {
    44.             return informationParts;
    45.         }
    46.  
    47.         void setInformationParts(List<ElementData> informationParts) {
    48.             this.informationParts = informationParts;
    49.         }
    50.  
    51.         void setInformation(String information) {
    52.             this.information = information;
    53.         }
    54.  
    55.         @Override
    56.         public String toString() {
    57.             return "XmlInfo [information=" + information
    58.                     + ", informationParts=" + informationParts + "]";
    59.         }
    60.     }
    61.  
    62.     public XmlInfo work(String input) {
    63.         XmlInfo xmlInfo = null;
    64.         try {
    65.             xmlInfo = tryToRead(input);
    66.         }
    67.         catch (XMLStreamException exception) {
    68.             exception.printStackTrace();
    69.         }
    70.         catch (FactoryConfigurationError error) {
    71.             error.printStackTrace();
    72.         }
    73.         return xmlInfo;
    74.     }
    75.  
    76.     private XmlInfo tryToRead(String input) throws FactoryConfigurationError,
    77.             XMLStreamException {
    78.         XMLStreamReader parser = openXmlParser(input);
    79.  
    80.         /*
    81.          * In diesem Objekt werden die aus der XML-Datei eingelesenen
    82.          * Informationen zusammengetragen:
    83.          */
    84.         XmlInfo xmlInfo = new XmlInfo();
    85.  
    86.         /* Das zuletzt geöffnete Elemente: */
    87.         String element = null;
    88.  
    89.         /* Gibt an, ob information offen ist: */
    90.         boolean informationIsOpen = false;
    91.  
    92.         /*
    93.          * Liste der anderen Unter-Informationen, die zu "information" gehören:
    94.          */
    95.         List<ElementData> informationParts = null;
    96.  
    97.         while (parser.hasNext()) {
    98.             parser.next();
    99.             switch (parser.getEventType()) {
    100.                 case XMLStreamConstants.START_ELEMENT:
    101.                     /* Wir merken uns, welches Element zuletzt geöffnet wurde: */
    102.                     element = parser.getLocalName();
    103.                     //System.out.println("Öffnendes Element: " + element);
    104.  
    105.                     /*
    106.                      * Falls sich information öffnet, merken wir uns, dass
    107.                      * dieses Element geöffnet ist und initialisieren das
    108.                      * Verzeichnis der anderen zur Information gehörenden Werte:
    109.                      */
    110.                     if ("information".equals(element)) {
    111.                         informationIsOpen = true;
    112.                         informationParts = new ArrayList<>();
    113.                     }
    114.                     break;
    115.                 case XMLStreamConstants.END_ELEMENT:
    116.                     switch (parser.getLocalName()) {
    117.                         case "information": {
    118.                             informationIsOpen = false;
    119.                             xmlInfo.setInformationParts(informationParts);
    120.                         }
    121.                     }
    122.                     break;
    123.                 case XMLStreamConstants.CDATA:
    124.                     System.out.println("CDATA: " + parser.getText());
    125.                     break;
    126.                 case XMLStreamConstants.SPACE:
    127.                     System.out.println("SPACE: " + parser.getText());
    128.                     break;
    129.                 case XMLStreamConstants.CHARACTERS:
    130.                     String characters = parser.getText();
    131.                     //System.out.println("CHARACTERS: " + characters);
    132.  
    133.                     /*
    134.                      * Wenn "information" geöffnet ist, aber nicht zuletzt
    135.                      * "information" geöffnet wurde, sondern ein anderes
    136.                      * Element, sichern wir dieses:
    137.                      */
    138.                     if (informationIsOpen) {
    139.                         /*
    140.                          * Falls das letzte öffnende Element information war,
    141.                          * die Information sichern:
    142.                          */
    143.                         if ("information".equals(element)) {
    144.                             xmlInfo.setInformation(characters);
    145.                         }
    146.                         /* anderenfalls die zusätzlichen Daten abspeichern: */
    147.                         else {
    148.                             informationParts.add(new ElementData(element, characters));
    149.                         }
    150.                     }
    151.                     break;
    152.             }
    153.         }
    154.         return xmlInfo;
    155.     }
    156.  
    157.     private XMLStreamReader openXmlParser(String input)
    158.             throws FactoryConfigurationError, XMLStreamException {
    159.         Reader reader = new StringReader(input);
    160.         XMLInputFactory factory = XMLInputFactory.newInstance();
    161.         XMLStreamReader parser = factory.createXMLStreamReader(reader);
    162.         return parser;
    163.     }
    164.  
    165.     public static void main(String[] args) {
    166.         XmlProblemDemonstration3 demo = new XmlProblemDemonstration3();
    167.         for (String input : new String[] {
    168.                 "<dinge><information>foo</information></dinge>",
    169.                 "<dinge><information>bar</information></dinge>",
    170.                 "<dinge><information>baz<oha>ueberraschung!</oha></information></dinge>",
    171.                 "<dinge><information>baz<oha>ueberraschung!</oha><oha>ueberraschung2!</oha></information></dinge>"
    172.                 }) {
    173.             System.out.println("Eingabe: " + input);
    174.             XmlInfo info = demo.work(input);
    175.             if (null == info) {
    176.                 System.out.println("Fehler in der Verarbeitung!");
    177.             }
    178.             else {
    179.                 System.out.println("Ergebnis: " + info);
    180.             }
    181.             System.out.println();
    182.         }
    183.     }
    184.  
    185. }

    Mit der Ausgabe:

    Code:
    Eingabe: <dinge><information>foo</information></dinge>
    Ergebnis: XmlInfo [information=foo, informationParts=[]]
    
    Eingabe: <dinge><information>bar</information></dinge>
    Ergebnis: XmlInfo [information=bar, informationParts=[]]
    
    Eingabe: <dinge><information>baz<oha>ueberraschung!</oha></information></dinge>
    Ergebnis: XmlInfo [information=baz, informationParts=[ElementData [element=oha, data=ueberraschung!]]]
    
    Eingabe: <dinge><information>baz<oha>ueberraschung!</oha><oha>ueberraschung2!</oha></information></dinge>
    Ergebnis: XmlInfo [information=baz, informationParts=[ElementData [element=oha, data=ueberraschung!], ElementData [element=oha, data=ueberraschung2!]]]
    Geändert von Crian (23.03.2014 um 12:46 Uhr)

  3. #3
    Global Moderator Floppy Disc Avatar von Landei
    Registriert seit
    31.07.2013
    Ort
    Sandersdorf-Brehna
    Fachbeiträge
    990
    Genannt
    163 Post(s)
    Blog-Einträge
    27
    Ohne mir das jetzt genauer angeschaut zu haben: Wenn du Markup hast, das zu den Daten und nicht zur eigentlichen Struktur des XMLs gehört, ist die beste Lösung normalerweise, die Daten mit Tags in eine CDATA-Sektion zu packen.
    Geändert von Landei (23.03.2014 um 15:20 Uhr)

  4. #4
    User Megabyte Avatar von Timothy_Truckle
    Registriert seit
    01.08.2013
    Ort
    Wasserkuppe
    Fachbeiträge
    1.329
    Genannt
    85 Post(s)
    Blog-Einträge
    5
    Zitat Zitat von Crian Beitrag anzeigen
    Ich bekomme von einem Kollegen eine XML-Datei, die mich vor ein unerwartetes Problem stellt.
    Habt ihr eine XSD vereinbart, die die Struktur der Datei beschreibt?

    Das solltet ihr unbedingt tun, denn dies bietet 2 Vorteile.
    1. Du kannst die Datei Deines Kollegen dagegen validieren und bei solchen "Überraschungen" intervenieren.
    2. Du kannst die das Parsen der Datei von JaxB, Castor oder ähnlichen Frameworks abnehmen lassen.
    bye
    TT

+ Antworten Thema als "gelöst" markieren

Direkt antworten Direkt antworten

Das Gegenteil von laut ist... ?

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 1 (Registrierte Benutzer: 0, Gäste: 1)

Ähnliche Themen

  1. Probleme mit der GUI
    Von Unregistriert im Forum AWT, Swing, JavaFX & SWT
    Antworten: 28
    Letzter Beitrag: 04.09.2013, 19:50
  2. (Threads) Neustart von run() in einem Runnable
    Von Crian im Forum Java-Grundlagen
    Antworten: 6
    Letzter Beitrag: 30.08.2013, 11:57
  3. Probleme mit GridBagLayout
    Von corvus im Forum AWT, Swing, JavaFX & SWT
    Antworten: 3
    Letzter Beitrag: 29.08.2013, 17:51
  4. CardLayout in einem GridbagLayout
    Von Unregistriert im Forum AWT, Swing, JavaFX & SWT
    Antworten: 9
    Letzter Beitrag: 14.02.2010, 12:03
  5. Java auf einem Pocket PC ?
    Von swerflash im Forum Java-Grundlagen
    Antworten: 7
    Letzter Beitrag: 15.05.2007, 11:57

Berechtigungen

  • Neue Themen erstellen: Ja
  • Themen beantworten: Ja
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •