xml fatal error umgehen

nazar

Mitglied
Sers,

beim Parsen meiner Xml-Files (<?xml version="1.0" encoding="UTF-8" standalone="no" ?>) lese ich einen Text aus, welcher vorher von einem Datensatz entschlüsselt wurde. Im besten Fall sind es Zahlen, wie "9994447773", im schlechtesten Sonderzeichen, wie "Ð,s+Þî?ÌÔ".
Das schafft der Parser nicht und wirft einen Fatal Error aus.

Java:
    /**
     * Xml-Daten extrahieren
     * @param _FileName
     */
    private void parseXml(String _FileName) {
        try {
            String fileName = _FileName;

            // ---- Parse XML file ----
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

            DocumentBuilder builder  = factory.newDocumentBuilder();
            Document        document = builder.parse( new File( fileName ) );

            showTagId       = searchXml(document, "ObjectEvent", "XXX_tid");
            showOriginal    = searchXml(document, "ObjectEvent", "XXX_originality");
            showEpc         = searchXml(document, "epcList", "epc");
            showAction      = searchXml(document, "ObjectEvent", "action");
            showSerialNo    = searchXml(document, "ObjectEvent", "XXX_serialnumber");
            showEventTime   = searchXml(document, "ObjectEvent", "eventTime");
        }
        catch( SAXParseException spe ) {
            System.out.println( "\n** Parsing error, line " + spe.getLineNumber() + ", uri "  + spe.getSystemId() );
            System.out.println( "   " + spe.getMessage() );
            Exception e = ( spe.getException() != null ) ? spe.getException() : spe;
            e.printStackTrace();
        }
        catch( SAXException sxe ) {
            Exception e = ( sxe.getException() != null ) ? sxe.getException() : sxe;
            e.printStackTrace();
        }
        catch( ParserConfigurationException pce ) {
            pce.printStackTrace();
        }
        catch( IOException ioe ) {
            ioe.printStackTrace();
        }
    }
Java:
    /**
     * durchsucht die Xml nach dem Wert von _Child und gibt ihn zurück
     * @param _Name
     * @param _Element
     * @param _Child
     * @return
     */
    private String searchXml(Document _Name, String _Element, String _Child) 
    {
        Document name = _Name;
        String element = _Element;
        String child = _Child;

        // ---- Get list of nodes to given tag ----
        NodeList ndList = name.getElementsByTagName( element );

        // ---- Loop through the list of main nodes ----
        for( int i=0; i<ndList.getLength(); i++ )
        {
            Node     nodeMain     = ndList.item( i );
            Node     nodeChild    = null;
            NodeList ndListChilds = nodeMain.getChildNodes();
            boolean  bChildFound  = false;
            if( null == ndListChilds )  continue;
            // Loop through the list of child nodes
            for( int j=0; j<ndListChilds.getLength(); j++ )
            {
                nodeChild = ndListChilds.item( j );
                if( null == nodeChild )  continue;
                String sNodeName = nodeChild.getNodeName();
                if( null == sNodeName )  continue;
                if( sNodeName.equals( child ) )
                {
                    bChildFound = true;
                    break;
                }
            }
            if (bChildFound == true) {
                return nodeChild.getFirstChild().getNodeValue();
            }
            else {
                return "unknown";
            }
        }
        return "unknown";
    }

Die fehlerhaften Zeichen befinden sich in "XXX_tid" und "XXX_serialnumber". Ich möchte gern alles als String woanders ausgeben. Aber das geht mit meiner bisherigen Methode wohl schlecht. Hat jemand einen Lösungsansatz oder einen Link, der mir hilft das ganze zu lösen ohne vorher die Xml-Files richtigzustellen?

Die "XXX_tid" und "XXX_serialnumber" können dabei ruhig verworfen, bzw. falsch zurückgegeben werden, wenn die Zeichen nicht stimmen. Hauptsache der Rest (und bei gültigen Files natürlich alles) wird angezeigt. :/
 
Zuletzt bearbeitet:
Wahrscheinlich sind die XML-Dateien gar nicht in UTF-8 gespeichert. Nur weil es als erste Zeile angegeben ist, kann die Datei auch als CPxxxx gespeichert sein, das soll nichts bedeuten. Ich würde das Dateiencoding checken...
 
Hmm, hab mir die Dateien jetzt mal als UTF-16 geben lassen. Dort sind sie doppelt so groß. Von daher geh ich mal von richtigem Encoding aus. Sollte beim Encoding irgendwas falsch sein würde es mir doch nichtmal der Browser anzeigen oder? Der Browser kann aber alles öffnen. Nur der parse-Befehl in java verhaut was. :/
 
Also mein Browser (Mozilla / Explorer) öffnet auch ohne Probleme XML-Dateien, die als UTF-8 gekennzeichnet, aber in CP1252 gespeichert wurden. Erzeuge doch mal selbst eine kleine Beispiel-Datei im UTF-8 Format und benutzt die zum Parsen. Dann weist Du 100%, das Du UTF-8 hast.
 
Hier mal der Code mit dem die Dateien erzeugt werden:
Java:
    /**
     *
     * Generiert das XML-Dokument
     */
    protected void printXml()
    {
        try {
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer t = null;

            t = tf.newTransformer();
            t.setOutputProperty( OutputKeys.ENCODING, "UTF-16");
            t.transform(new DOMSource(newDoc()), new StreamResult(szSaveXml + sFileName + ".xml"));
        }
        catch (Exception ex) {
            System.err.println("xml file couldn't be created");
        }
    }
Hab damit die UTF-8 und UTF-16 erzeugt. Beides war mit Sonderzeichen im Text nicht lesbar. Bei UTF-16 bin ich ja noch davon ausgegangen, dass alles lesbar sein müsste.
Falls es auch noch interessant ist, hier der Aufbau des Dokuments:
Java:
    /**
     *
     * Bauplan des XML-Dokuments
     * @return
     */
    protected Document newDoc()
    {
        DocumentBuilderFactory docBFac;
        DocumentBuilder docBuild;
        try
        {
            docBFac = DocumentBuilderFactory.newInstance();
            docBuild = docBFac.newDocumentBuilder();
            doc = docBuild.newDocument();
        }
        catch( Exception e )
        {
            System.err.println("xml file couldn't be created");
        }
        if (doc != null)
        {
            Element root = doc.createElement("XML-Datei");

            Date dt = new Date(); // für CreationDate der XML-Datei

            root.setAttribute("FileName", sFileName);
            root.setAttribute("CreationDate", String.valueOf(dt));

            Element_EventList = doc.createElement("EventList");

            Element_ObjectEvent = doc.createElement("ObjectEvent");

            Element_EpcList = doc.createElement("epcList");

            Element_BizLocation = doc.createElement("bizLocation");

            Element eventTime = doc.createElement("eventTime");
            eventTime.appendChild(doc.createTextNode(sEventTime));
            Element_ObjectEvent.appendChild(eventTime);

            Element eventTimeZoneOffset = doc.createElement("eventTimeZoneOffset");
            eventTimeZoneOffset.appendChild(doc.createTextNode(sEventTimeZoneOffset));
            Element_ObjectEvent.appendChild(eventTimeZoneOffset);

            Element epc = doc.createElement("epc");
            epc.appendChild(doc.createTextNode(sEpc));
            Element_EpcList.appendChild(epc);

            Element_ObjectEvent.appendChild(Element_EpcList);

            Element action = doc.createElement("action");
            action.appendChild(doc.createTextNode(sAction));
            Element_ObjectEvent.appendChild(action);

            Element id = doc.createElement("id");
            id.appendChild(doc.createTextNode(sId));
            Element_BizLocation.appendChild(id);

            Element_ObjectEvent.appendChild(Element_BizLocation);

            Element tid = doc.createElement("XXX_tid");
            tid.appendChild(doc.createTextNode(sTid));
            Element_ObjectEvent.appendChild(tid);

            Element originality = doc.createElement("XXX_originality");
            originality.appendChild(doc.createTextNode(sOriginality));
            Element_ObjectEvent.appendChild(originality);

            Element readerid = doc.createElement("XXX_readerid");
            readerid.appendChild(doc.createTextNode(sReaderId));
            Element_ObjectEvent.appendChild(readerid);

            Element companyprefix = doc.createElement("XXX_companyprefix");
            companyprefix.appendChild(doc.createTextNode(sCompanyPrefix));
            Element_ObjectEvent.appendChild(companyprefix);

            Element itemreference = doc.createElement("XXX_itemreference");
            itemreference.appendChild(doc.createTextNode(sItemReference));
            Element_ObjectEvent.appendChild(itemreference);

            Element serialnumber = doc.createElement("XXX_serialnumber");
            serialnumber.appendChild(doc.createTextNode(sSerialNumber));
            Element_ObjectEvent.appendChild(serialnumber);

            Element machineid = doc.createElement("XXX_machineid");
            machineid.appendChild(doc.createTextNode(sMachineId));
            Element_ObjectEvent.appendChild(machineid);

            Element checkpoint = doc.createElement("XXX_checkpoint");
            checkpoint.appendChild(doc.createTextNode(sCheckpoint));
            Element_ObjectEvent.appendChild(checkpoint);

            Element technology = doc.createElement("XXX_technology");
            technology.appendChild(doc.createTextNode(sTechnology));
            Element_ObjectEvent.appendChild(technology);

            Element_EventList.appendChild(Element_ObjectEvent);
            root.appendChild(Element_EventList);
            doc.appendChild(root);

        }
        return doc;
    }
Würde ja gern ein kleines funktionierendes Beispiel hochladen, allerdings wird das schwierig, da es zusammen mit encrypt/decrypt trotzdem ziemlich kompliziert wird und noch eine PLC dranhängt. :/

Aber um das Problem vllt nochmal zu verdeutlichen.
Letztendlich wirft Zeile 13. im ersten Post eben die Exception (+ Fatal Error), dass bestimmte Characters nicht gelesen werden können. Auch bei UTF-16, was mich besonders verwundert.
Danke für die bisherige Mühe fastjack.
 
Zuletzt bearbeitet:
echtes utf-8 sollte reichen, spezielle XML Character werden aber doch wohl hoffentlich escaped?
 
Nunja, ob sie so speziell sind weiß ich nicht. Ich schließe bei der Xml-Erzeugung keine Character aus. Alles was mir die AES-Entschlüsselung gibt, wird so niedergeschrieben wie ich es bekomme, was im besten Fall eben normale Zahlen sind. Sollte allerdings irgend ein Blödsinn von meiner Hardware eingelesen werden, sind Zeichenfolgen wie "|½TèQ«¿ *", "Ð,s+Þî?ÌÔ", "Ü9ˆ?ÇüÆÞ" oder "ÄkQÕÇäb] H" möglich.
Wie schließe ich denn bestimmte Chracters aus oder maskiere sie bei der File-Generierung?
Da Files mit solchen Zeichen sowieso schon als Fehlerfiles markiert sind und zur Weiterverarbeitung nur noch Daten relevant wären, bei denen solche Sonderzeichen nicht vorkommen, wäre mir Ausschluss oder Maskierung der Zeichen ganz recht.
 
Zuletzt bearbeitet:
K, danke, dass CDATA kannte ich z. B. garnicht.
Aber ist das im Sinne des Erfinders oder sollte ich es vor und nach "epc" einbauen?

<epc><![CDATA[—O~Ÿµ-”W]]></epc>

Aufjedenfall kommt da weiterhin:
Java:
[Fatal Error] R535_113605_XXX_Chain_Left_2010-11-29_10-56-37-860_fake.xml:1:328: Character reference "&#27" is an invalid XML character.
org.xml.sax.SAXParseException: Character reference "&#27" is an invalid XML character.

        at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:239)
        at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:283)
        at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:208)
        at beans.XXXXmlPanel.parseXml(XXXXmlPanel.java:188)
        at beans.XXXXmlPanel.access$300(XXXXmlPanel.java:15)
        at beans.XXXXmlPanel$3.valueChanged(XXXXmlPanel.java:135)
        at javax.swing.JList.fireSelectionValueChanged(JList.java:1765)
** Parsing error, line 1, uri file:/C:/XXX/XML/Testdokumente/R535_113605_XXX_Chain_Left_2010-11-29_10-56-37-860_fake.xml
   Character reference "&#27" is an invalid XML character.
        at javax.swing.JList$ListSelectionHandler.valueChanged(JList.java:1779)
        at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:167)
        at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:147)
        at javax.swing.DefaultListSelectionModel.fireValueChanged(DefaultListSelectionModel.java:194)
        at javax.swing.DefaultListSelectionModel.changeSelection(DefaultListSelectionModel.java:388)
        at javax.swing.DefaultListSelectionModel.changeSelection(DefaultListSelectionModel.java:398)
        at javax.swing.DefaultListSelectionModel.setSelectionInterval(DefaultListSelectionModel.java:442)
        at javax.swing.JList.setSelectionInterval(JList.java:2035)
        at javax.swing.plaf.basic.BasicListUI$Handler.adjustSelection(BasicListUI.java:2728)
        at javax.swing.plaf.basic.BasicListUI$Handler.mousePressed(BasicListUI.java:2684)
        at java.awt.AWTEventMulticaster.mousePressed(AWTEventMulticaster.java:263)
        at java.awt.Component.processMouseEvent(Component.java:6131)
        at javax.swing.JComponent.processMouseEvent(JComponent.java:3265)
        at java.awt.Component.processEvent(Component.java:5899)
        at java.awt.Container.processEvent(Container.java:2023)
        at java.awt.Component.dispatchEventImpl(Component.java:4501)
        at java.awt.Container.dispatchEventImpl(Container.java:2081)
        at java.awt.Component.dispatchEvent(Component.java:4331)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4301)
        at java.awt.LightweightDispatcher.processMouseEvent(Container.java:3962)
        at java.awt.LightweightDispatcher.dispatchEvent(Container.java:3895)
        at java.awt.Container.dispatchEventImpl(Container.java:2067)
        at java.awt.Window.dispatchEventImpl(Window.java:2458)
        at java.awt.Component.dispatchEvent(Component.java:4331)
        at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
        at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
        at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
        at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

Bisschen frustrierend. ^^
Ich probiers nochmal und weiß gleich das Element als CDATA aus. Allerdings dürfte sich da (laut meinem schnell angelesen 5-linkwissen) ja nicht viel ändern. :X
 
Die Macht der Sonderzeichen. >_<

Java:
            Element epc = doc.createElement("epc"); 
            epc.appendChild(doc.createCDATASection(sEpc));
            //epc.appendChild(doc.createTextNode(sEpc));
            Element_EpcList.appendChild(epc);

Hab mal ein XML als Beispiel angehängt. Evtl. ein Extremfall, aber zeigt glaub ich, dass CDATA nicht wirklich funktioniert.
 

Anhänge

Hab mal ein XML als Beispiel angehängt. Evtl. ein Extremfall, aber zeigt glaub ich, dass CDATA nicht wirklich funktioniert.
XML ist textbasiert, wenn du Binärdaten darin ablegen willst, solltest du sie vorher konvertieren, Base64 wird da meist verwendet.
 
Ich weiß ja nicht, dass Binärdaten kommen. Wenn ich die erhaltenen Daten mit Base64 konvertier ändert es mir doch auch die normalen Daten wie 3336662225 um. :/
Ich glaub ich versuch jetzt bei einer Exception das ganze als String einzulesen, die zwei fehlerhaften Elemente auszuschneiden/ersetzen und danach nochmal parsen.
 
Ich weiß ja nicht, dass Binärdaten kommen.
Du weisst dass es welche sein können, und damit ist es eben nicht immer nurText:
Alles was mir die AES-Entschlüsselung gibt, wird so niedergeschrieben wie ich es bekomme, was im besten Fall eben normale Zahlen sind.

Wenn ich die erhaltenen Daten mit Base64 konvertier ändert es mir doch auch die normalen Daten wie 3336662225 um. :/
Richtig, und es entstehen keine illegalen Zeichenketten.
Zurückkonvertieren ist ja auch kein Problem, google mal nach "xml binary data".
 
Sooo, danke für eure Mühe. Ich lese das ganze jetzt als String ein und schneid die Teile aus. Da ich die Xml-Dateien auch am Browser mit Originaldaten sehen will fand ich die Lösung am besten.
 

Zurück
Oben