All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sta.cts.XMLElement Maven / Gradle / Ivy


package com.sta.cts;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Serializable;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import com.sta.mlogger.MLogger;

/**
 * 

Name: XMLElement

*

Description: Abbildung eines XML-Tags samt NameSpace, NameSpace-Name, * Attributen und untergeordneter Struktur beim Parsen einer XML-Struktur * mit dem XMLScanner. *

*

Comment: Prim?res Ziel bei der urspr?nglichen Erstellung diese Klasse war * die Unterst?tzung von SOAP-Web-Services. Dabei ging es darum, SOAP-Messages * zu analysieren (zu parsen), um diese auszuwerten und weiterzuverarbeiten. * Im n?chsten Schritt wurde Serializable implementiert, um eine * Bin?r-Serialisierung zu erm?glichen. Au?erdem wurden genXMLStructure-Methoden * erg?nzt. *

*

Copyright: Copyright (c) 2014, 2016, 2017, 2019, 2021

*

Company: >StA-Soft<

* @author StA * @version 1.0 */ public class XMLElement implements Serializable { /** * Die serialVersionUID. */ static final long serialVersionUID = 1813524552145780368L; //=========================================================================== /** * Tag-Name des XML-Elements. */ private String myTagName; /** * NameSpace (ggf. ermittelt/aufgel?st) des XML-Tags. */ private String myNameSpace; /** * NameSpace-Name des XML-Tags, falls angegeben. */ private String myNameSpaceName; /** * Text bzw. textueller Inhalt, falls vorhanden, des XML-Tags. */ private String myText; /** * Vector mit untergeordneten XML-Elementen. */ private Vector myElementsV; /** * Hash-Tabelle mit untergeordneten XML-Elementen. Falls ein Element mehrfach * vorhanden ist, wird statt des Elements ein Vector in die Hash-Tabelle * eingetragen, in der alle Elemente mit gleichem Namen enthalten sind. */ private Hashtable myElementsHT; /** * Attribute (Name-Wert-Paare). */ private Hashtable myAttributesHT; //=========================================================================== /** * Standard-Constructor. */ public XMLElement() { } /** * Constructor mit Tag-Name. * @param pTagName Tag-Name */ public XMLElement(String pTagName) { myTagName = pTagName; } /** * Constructor mit Tag-Name und NameSpace-Name (!). * @param pTagName Tag-Name * @param pNameSpaceName NameSpace-Name */ public XMLElement(String pTagName, String pNameSpaceName) { myTagName = pTagName; myNameSpaceName = pNameSpaceName; } /** * Spezial-Constructor mit Tag-Name und einem XML-Element. * Dabei wird der Inhalt (!) des ?bergebenen Elements (also dessen Attribute, * untergeordneten XML-Elemente und Text) in das neu zu erstellende * XML-Element eingef?gt. * @param pTagName Tag-Name * @param pElement XML-Element */ public XMLElement(String pTagName, XMLElement pElement) { myTagName = pTagName; copyFromAET(pElement); } /** * Spezial-Constructor mit Tag-Name, NameSpace-Name (!) und einem XML-Element. * Dabei wird der Inhalt (!) des ?bergebenen Elements (also dessen Attribute, * untergeordneten XML-Elemente und Text) in das neu zu erstellende * XML-Element eingef?gt. * @param pTagName Tag-Name * @param pElement XML-Element * @param pNameSpaceName NameSpace-Name */ public XMLElement(String pTagName, String pNameSpaceName, XMLElement pElement) { myTagName = pTagName; myNameSpaceName = pNameSpaceName; copyFromAET(pElement); } //=========================================================================== /** * Tag-Name vorgeben. * @param pTagName Tag-Name */ public void setTagName(String pTagName) { myTagName = pTagName; } /** * Tag-Name ermitteln. * @return Tag-Name */ public String getTagName() { return myTagName; } /** * NameSpace vorgeben. Dazu soll der NameSpace vorher aufgel?st werden. * @param pNameSpace NameSpace */ public void setNameSpace(String pNameSpace) { myNameSpace = pNameSpace; } /** * NameSpace ermitteln. * @return NameSpace */ public String getNameSpace() { return myNameSpace; } /** * NameSpace-Name vorgeben. Das ist der Name, der (falls vorhanden) vor dem * Tag-Namen steht. * @param pNameSpaceName NameSpace-Name */ public void setNameSpaceName(String pNameSpaceName) { myNameSpaceName = pNameSpaceName; } /** * NameSpace-Name ermitteln. Das ist der Name, der (falls vorhanden) vor dem * Tag-Namen steht. Dieser Name muss bei Bedarf bzw. zur Verwendung aufgel?st * werden. * @return NameSpace-Name */ public String getNameSpaceName() { return myNameSpaceName; } /** * Text bzw. textueller Inhalt, falls vorhanden, des XML-Tags vorgeben. * XML-Tags mit (ausschlie?lich) untergeordneten XML-Tags haben keinen Text. * Leere XML-Tags (bzw. ein ?ffnendes und schlie?endes XML-Tag direkt * nacheinander) haben einen Leer-String ("") als Text. * @param pText Text */ public void setText(String pText) { myText = pText; } /** * Text bzw. textuellen Inhalt, falls vorhanden, des XML-Tags ermitteln * XML-Tags mit (ausschlie?lich) untergeordneten XML-Tags haben keinen Text. * Leere XML-Tags (bzw. ein ?ffnendes und schlie?endes XML-Tag direkt * nacheinander) haben einen Leer-String ("") als Text. * @return Text */ public String getText() { return myText; } /** * XML-Element hinzuf?gen. Der Name des XML-Elements soll gesetzt sein. * Das XML-Element wird am Ende des Vectors hinzugef?gt und unter dem * Tag-Namen in die Hash-Tabelle eingef?gt. * Neu: Falls der Tag-Name nicht gesetzt ist, entf?llt das Einf?gen in die * Hash-Tabelle. Verwendet wird dies f?r reine Text-Teile. * @param element XML-Element */ public void addElement(XMLElement element) { if (myElementsV == null) { myElementsV = new Vector(); } myElementsV.add(element); String tagname = element.getTagName(); if (tagname != null) { if (myElementsHT == null) { myElementsHT = new Hashtable(); } Object obj = myElementsHT.get(tagname); if (obj == null) { myElementsHT.put(tagname, element); } else if (obj instanceof XMLElement) { Vector v = new Vector(); v.add(obj); v.add(element); myElementsHT.put(tagname, v); } else if (obj instanceof Vector) { Vector v = (Vector) obj; v.add(element); } } } /** * Anzahl der XML-Elemente im Vector ermitteln, das entspricht also der * Anzahl der untergeordneten XML-Tags. * @return Anzahl der XML-Elemente */ public int getElementCount() { return myElementsV != null ? myElementsV.size() : 0; } /** * Element an einem Index im Vector ermitteln. * Falls kein Element im Vector vorhanden oder der Index zu gro? ist, wird * eine ArrayIndexOutOfBoundsException ausgel?st. * @param i Index f?r Vector * @return XML-Element */ public XMLElement getElement(int i) { if (myElementsV == null) { throw new ArrayIndexOutOfBoundsException(i); } return myElementsV != null ? myElementsV.get(i) : null; } /** * XML-Element mit bestimmtem Tag-Namen ermitteln. Falls mehrere gleichnamige * XML-Elemente vorhanden sind, wird das erste geliefert. * @param tagname Tag-Name * @return XML-Element, falls vorhanden, sonst null */ public XMLElement getElement(String tagname) { if (myElementsHT == null) { return null; } Object obj = myElementsHT.get(tagname); if (obj instanceof XMLElement) { return (XMLElement) obj; } else if (obj instanceof Vector) { Vector v = (Vector) obj; if (v.size() >= 1) { return (XMLElement) v.get(0); } return null; } return null; } /** * Text eines untergeordneten Tag ermitteln, falls das Tag vorhanden ist und * einen Text enth?lt. Sind mehrere Tag mit dem gleichen Namen vorhanden, * wird der Text vom ersten dieser Tag ermittelt. * @param tagname Tag-Name * @return Text, falls Tag und Text vorhanden, sonst null */ public String getText(String tagname) { XMLElement element = getElement(tagname); return element != null ? element.getText() : null; } /** * Anzahl der XML-Elemente mit einem bestimmten Tag-Namen ermitteln. * @param tagname Tag-Name * @return Anzahl der XML-Element mit dem Tag-Namen */ public int getElementCount(String tagname) { if (myElementsHT == null) { return 0; } Object obj = myElementsHT.get(tagname); if (obj instanceof XMLElement) { return 1; } else if (obj instanceof Vector) { Vector v = (Vector) obj; return v.size(); } return 0; } /** * XML-Element an bestimmter Position aus der Menge der XML-Elemente mit * einem bestimmten Tag-Namen ermitteln. * Ist kein Tag mit diesem Namen vorhanden, wird null als Ergebnis geliefert, * also analog getElement(String). * Ist mind. ein Tag mit diesem Namen vorhanden und der Index kleiner 0 oder * zu gro?, dann wird eine ArrayIndexOutOfBoundsException ausgel?st, also * analog zu getElement(int). * @param tagname Tag-Name * @param i Index in der Menge der XML-Element mit einem bestimmten Tag-Namen * @return XML-Element, falls vorhanden (null, falls nicht vorhanden) */ public XMLElement getElement(String tagname, int i) { if (myElementsHT == null) { // throw new ArrayIndexOutOfBoundsException(i); return null; } Object obj = myElementsHT.get(tagname); if (obj instanceof XMLElement) { if (i != 0) { throw new ArrayIndexOutOfBoundsException(i); } return (XMLElement) obj; } else if (obj instanceof Vector) { Vector v = (Vector) obj; return (XMLElement) v.get(i); } return null; } /** * Text eines untergeordneten Tag ermitteln, falls das Tag vorhanden ist und * einen Text enth?lt. * @param tagname Tag-Name * @param i Index * @return Text, falls Tag und Text vorhanden, sonst null */ public String getText(String tagname, int i) { XMLElement element = getElement(tagname, i); return element != null ? element.getText() : null; } /** * Attribut hinzuf?gen. * @param attrname Attribut-Name * @param attrvalue Attribut-Wert */ public void addAttribute(String attrname, String attrvalue) { if (myAttributesHT == null) { myAttributesHT = new Hashtable(); } if (attrvalue != null) { myAttributesHT.put(attrname, attrvalue); } else { myAttributesHT.remove(attrname); } } /** * Attribut-Wert ermitteln. * @param attrname Attribut-Name * @return Attribut-Wert */ public String getAttribute(String attrname) { return myAttributesHT != null ? myAttributesHT.get(attrname) : null; } /** * Menge der Attribut-Namen ermitteln. * @return Menge der Attribut-Namen */ public Enumeration getAttributeNames() { return myAttributesHT != null ? myAttributesHT.keys() : null; } /** * Element an Index i l?schen. * @param i Index * @return gel?schtes Element, falls vorhanden */ public XMLElement removeElement(int i) { if (myElementsV != null) { XMLElement element = myElementsV.remove(i); if (myElementsHT != null) { String tagname = element.getTagName(); Object obj = myElementsHT.get(tagname); if (obj instanceof XMLElement) { myElementsHT.remove(tagname); } else if (obj instanceof Vector) { Vector v = (Vector) obj; v.remove(element); } } return element; } return null; } /** * Element in der Menge der Elemente mit einem bestimmten Namen * l?schen. * @param tagname Tag-Name * @return gel?schtes Element, falls vorhanden */ public XMLElement removeElement(String tagname) { if (myElementsHT == null) { // throw new ArrayIndexOutOfBoundsException(i); return null; } Object obj = myElementsHT.get(tagname); if (obj instanceof XMLElement) { if (myElementsV != null) { myElementsV.removeElement(obj); } return (XMLElement) obj; } else if (obj instanceof Vector) { Vector v = (Vector) obj; XMLElement element = (XMLElement) v.remove(0); if (myElementsV != null) { myElementsV.removeElement(obj); } return element; } return null; } /** * Element an Index i in der Menge der Elemente mit einem bestimmten Namen * l?schen. * @param tagname Tag-Name * @param i Index * @return gel?schtes Element, falls vorhanden */ public XMLElement removeElement(String tagname, int i) { if (myElementsHT == null) { // throw new ArrayIndexOutOfBoundsException(i); return null; } Object obj = myElementsHT.get(tagname); if (obj instanceof XMLElement) { if (i != 0) { throw new ArrayIndexOutOfBoundsException(i); } if (myElementsV != null) { myElementsV.removeElement(obj); } return (XMLElement) obj; } else if (obj instanceof Vector) { Vector v = (Vector) obj; XMLElement element = (XMLElement) v.remove(i); if (myElementsV != null) { myElementsV.removeElement(obj); } return element; } return null; } /** * Alle Elemente l?schen. */ public void removeElements() { if (myElementsHT != null) { myElementsHT.clear(); } if (myElementsV != null) { myElementsV.clear(); } } //--------------------------------------------------------------------------- /** * Attribute, untergeordnete Elemente und Text, soweit vorhanden, vom * ?bergebenen Element (ersetzend) ?bernehmen. * @param pElement XML-Element, von dem Attribute, Element und Text ?bernommen * werden sollen */ public void copyFromAET(XMLElement pElement) { myAttributesHT = pElement.myAttributesHT; myElementsHT = pElement.myElementsHT; myElementsV = pElement.myElementsV; myText = pElement.myText; } //--------------------------------------------------------------------------- /** * XML-Struktur erstellen. Realisiert wurde der allgemeine Fall, also * unabh?ngig davon, ob es sich um ein XML-Tag mit/ohne oder um reinen Text * handelt. Somit sind auch Dummy-Ebenen m?glich (Elemente ohne Tag-Name, * ohne Attribute, ohne untergeordnete Elemente und ohne Text). * @param xg XML-Generator * @throws IOException im Fehlerfall */ public void genXMLStructure(XMLGenerator xg) throws IOException { // ?ffnendes Tag if (myTagName != null) { xg.openTag((myNameSpaceName != null ? myNameSpaceName + ":" : "") + myTagName); } // Attribute eigentlich nur, falls Tag-Name vorhanden Enumeration e = getAttributeNames(); if (e != null) { while (e.hasMoreElements()) { String attrname = e.nextElement(); String attrvalue = getAttribute(attrname); xg.putAttr(attrname, attrvalue); } } // Attribute eigentlich auch nur, falls Tag-Name vorhanden if (myElementsV != null) { int size = myElementsV.size(); for (int i = 0; i < size; i++) { XMLElement element = myElementsV.get(i); element.genXMLStructure(xg); } } // Text in beiden F?llen, mit und ohne Tag-Name if (myText != null) { xg.putContent(myText); } // schlie?endes Tag if (myTagName != null) { xg.closeTag((myNameSpaceName != null ? myNameSpaceName + ":" : "") + myTagName); } } /** * XML-Struktur erstellen (incl. XML-Header). * @param pEnc Codierung, z. B. UTF-8 oder ISO-8859-1 * @return String-Darstellung der XML-Struktur * @throws IOException im Fehlerfall */ public String genXMLStructure(String pEnc) throws IOException { XMLGenerator xg = new XMLGenerator(); StringWriter sw = new StringWriter(); xg.createXML(new BufferedWriter(sw), pEnc); genXMLStructure(xg); xg.closeXML(); return sw.toString(); } /** * XML-Struktur mit Standard-Codierung (aktuell ISO-8859-1) erstellen (incl. * XML-Header). * @return String-Darstellung der XML-Struktur * @throws IOException im Fehlerfall */ public String genXMLStructure() throws IOException { return genXMLStructure((String) null); } /** * XML-Struktur erstellen (incl. XML-Header) und in Datei speichern. * @param fn Dateiname * @param pEnc Codierung, z. B. UTF-8 oder ISO-8859-1 * @throws IOException im Fehlerfall */ public void genXMLStructureToFile(String fn, String pEnc) throws IOException { XMLGenerator xg = new XMLGenerator(); xg.createXML(fn, pEnc); genXMLStructure(xg); xg.closeXML(); } /** * XML-Struktur mit Standard-Codierung (aktuell ISO-8859-1) erstellen (incl. * XML-Header) und in Datei speichern. * @param fn Dateiname * @throws IOException im Fehlerfall */ public void genXMLStructureToFile(String fn) throws IOException { genXMLStructureToFile(fn, null); } //--------------------------------------------------------------------------- /** * String-Darstellung mit Einr?ckung ermitteln. Wird zu Debug-Zwecken * verwendet. * @param indent Einr?ckung (Anzahl der Leerzeichen) * @return String-Darstellung */ public String toString(int indent) { String s = MLogger.indent(indent); StringBuilder sb = new StringBuilder(); sb.append(s + "Element...\n"); sb.append(s + " NameSpaceName: " + myNameSpaceName + "\n"); sb.append(s + " TagName: " + myTagName + "\n"); sb.append(s + " NameSpace: " + myNameSpace + "\n"); sb.append(s + " Text: " + myText + "\n"); if (myElementsV != null) { sb.append(s + " Elements...\n"); int size = myElementsV.size(); for (int i = 0; i < size; i++) { XMLElement element = myElementsV.get(i); sb.append(element.toString(indent + 2)); } sb.append(s + " Elements: Ok.\n"); } sb.append(s + "Element: Ok.\n"); return sb.toString(); } @Override public String toString() { return "Document...\n" + toString(1) + "Document: Ok."; } //=========================================================================== /** * XML-Struktur parsen, XMLElement-Struktur erstellen und zur?ckliefern, dabei * die NameSpaces beachten (registrieren, aufl?sen, in XMLElement-Struktur * eintragen). * @param xs XML-Scanner (initialisiert) * @param xns XMLNameSpace von ggf. ?bergeordneten Strukturen, sonst null * @return XMLElement-Struktur oder null, falls nichts zu parsen war * @throws Exception im Fehlerfall (Lesefehler, XML-Fehler/Struktur-Fehler) */ public static XMLElement parseXMLStructure(XMLScanner xs, XMLNameSpace xns) throws Exception { XMLElement res = null; Object obj = xs.getToken(); if (obj instanceof XMLTag) { XMLTag t = (XMLTag) obj; if (t.isOpen()) { if (t.isClose()) { t.resOpen(); xs.ungetToken(t); } String name = t.getName(); XMLElement element = new XMLElement(name); String nsn = t.getNameSpace(); XMLNameSpace xns1 = null; Enumeration names = t.getAttrNames(); if (names != null) { while (names.hasMoreElements()) { String attrname = names.nextElement(); String attrvalue = t.getAttr(attrname); if (attrname.equals("xmlns")) { // String ns1 = attrvalue; if (xns1 == null) { xns1 = new XMLNameSpace(xns); } xns1.setStdNameSpace(attrvalue); } else if (attrname.startsWith("xmlns:") && (attrname.length() > 6)) { String nsn1 = attrname.substring(6); // String ns1 = attrvalue; if (xns1 == null) { xns1 = new XMLNameSpace(xns); } xns1.addNameSpace(nsn1, attrvalue); } /* else { // "normales" Attribut // // element.addAttribute(attrname, t.getAttr(attrname)); // // Potentielles Problem: // Die Namespace-Attribute werden dann nicht als solche weitergegeben. // M?gliche L?sung: // Alle Attribute ?bernehmen, dann muss eine Unterscheidung zw. // NameSpace- und Nicht-NameSpace-Attributen bei der Verwendung // erfolgen. } */ // alle Attribute ?bernehmen element.addAttribute(attrname, attrvalue); } } xns1 = xns1 != null ? xns1 : xns; if (nsn == null) { if (xns1 != null) { element.setNameSpace(xns1.getStdNameSpace()); } } else { element.setNameSpaceName(nsn); if (xns1 != null) { element.setNameSpace(xns1.getNameSpace(nsn)); } else { // Fehler! NameSpaceName angegeben, aber nicht definiert. MLogger.wrn("Missing definition for name space name '" + nsn + "'."); } } /* XMLElement element1; while ((element1 = parseXMLStructure(xs, xns1)) != null) { element.addElement(element1); } obj = xs.getToken(); if (obj instanceof String) { element.setText((String) obj); obj = xs.getToken(); } */ while (true) { XMLElement element1 = parseXMLStructure(xs, xns1); if (element1 != null) { String text = element.getText(); if (text != null) { XMLElement element2 = new XMLElement(); element2.setText(text); element.addElement(element2); element.setText(null); } element.addElement(element1); } else { obj = xs.getToken(); if (obj instanceof String) { if (element.getElementCount() > 0) { XMLElement element2 = new XMLElement(); element2.setText((String) obj); element.addElement(element2); } else { element.setText((String) obj); } } else { break; } } } if (obj instanceof XMLTag) { t = (XMLTag) obj; if (!t.isOpen() && t.isClose() && name.equals(t.getName())) { // ok res = element; } else { // Fehler throw new Exception("XML-Error: Invalid end tag (" + name + ")."); } } else { // Fehler throw new Exception("XML-Error: Missing end tag (" + name + ")."); } } else { xs.ungetToken(obj); } } else if (obj != null) { xs.ungetToken(obj); } return res; } /** * XML-Struktur parsen, XMLElement-Struktur erstellen und zur?ckliefern, dabei * die NameSpaces beachten (registrieren, aufl?sen, in XMLElement-Struktur * eintragen). * @param fn Dateiname * @param xns XMLNameSpace von ggf. ?bergeordneten Strukturen, sonst null * @return XMLElement-Struktur oder null, falls nichts zu parsen war * @throws Exception im Fehlerfall (Lesefehler, XML-Fehler/Struktur-Fehler) */ public static XMLElement parseXMLStructureFromFile(String fn, XMLNameSpace xns) throws Exception { XMLElement res = null; XMLScanner xs = new XMLScanner(); try { xs.init(fn); xs.initH(null); // xs.initXS(); // hier nicht n?tig, da Initialisierung mit Dateiname res = XMLElement.parseXMLStructure(xs, xns); } finally { xs.done(); } return res; } /** * XML-Struktur parsen, XMLElement-Struktur erstellen und zur?ckliefern, dabei * die NameSpaces beachten (registrieren, aufl?sen, in XMLElement-Struktur * eintragen). * @param xml die XML-Struktur als Text * @param xns XMLNameSpace von ggf. ?bergeordneten Strukturen, sonst null * @return XMLElement-Struktur oder null, falls nichts zu parsen war * @throws Exception im Fehlerfall (Lesefehler, XML-Fehler/Struktur-Fehler) */ public static XMLElement parseXMLStructureFromText(String xml, XMLNameSpace xns) throws Exception { XMLElement res = null; XMLScanner xs = new XMLScanner(); try { xs.init(new StringReader(xml)); xs.initH(null); xs.initXS(); // hier n?tig, da Initialisierung mit Reader res = XMLElement.parseXMLStructure(xs, xns); } finally { xs.done(); } return res; } //=========================================================================== /** * Test-Methode: Parsen einer XML-Datei und Ausgabe der XMLElement-Struktur. * @param fn Dateiname */ public static void run(String fn) { try { XMLScanner xs = new XMLScanner(); xs.init(fn); xs.initH(null); try { XMLElement element = XMLElement.parseXMLStructure(xs, null); if (element != null) { MLogger.deb(element::toString); } else { MLogger.deb("Result: null"); } } finally { xs.done(); } } catch (Exception ex) { MLogger.err("", ex); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy