XMLConfiguration(1.10)/getString : Wert "E" aus <version type="Auto">E</version>n lesen

HRX

Mitglied
Hallo zusammen,

ich möchte eine xml-Datei auslesen.

Darin kommen folgende Zeilen vor:

<versions>
<version type="Auto">E</version>
<version type="LKW">F</version>
<version type="Krad">G</version>
</versions>

Ich möchte den Wert "E" aus der ersten Zeile auslesen.

So weit bin ich bisher gekommen :


Java:
try
        {
            config = new XMLConfiguration("Z:\\config.xml");
            // do something with config
        }
        catch( ConfigurationException cex)
        {
            // something went wrong, e.g. the file was not found
        }
       
       
        String devType = config.getString("sensor.versions.version[@type='Auto']");

Leider hat devType hinterher den Wert 'null', also wurde nichts gefunden.

Nehme ich
Java:
devType = config.getString("sensor.versions.version[@type]");
bekomme ich als Wert "Auto".


Das ist dann der Wert des ersten
<versions>
<version type= ..>
Das gefunden wird.

Das ist aber nicht, das was ich suche.

Könnte mir bitte jemand auf die Sprünge helfen ?

Viele Grüße
 

HRX

Mitglied
Du hast es nicht erwähnt, aber ich gehe davon aus, dass Du Apache Commons nutzt (die Klasse XMLConfiguration).

Du versuchst, per XPATH zuzugreifen. Laut HowTo ist es dazu notwendig, dass man die XPathExpressionEngine nutzt / konfiguriert:

Hast Du die auch schon gesetzt wie im HowTo beschrieben?
Hallo Super Tipp , Danke dafür !!!

Hatte ich natürlich nicht gesetzt :-|

Jetzt noch ein kleine Zusatzfrage, ich das XML-Dokument ist bereits in einem String.
Leider gibt es keine Constructor
XMLConfiguration(String S);

Oder habe ich (wieder) etwas übersehen.

VG
 

KonradN

Super-Moderator
Mitarbeiter
Nutzt Du noch die alte Version 1.1? Das wäre dann ja diese Klasse:

Da gibt es keinen passenden Konstruktor. Aber da geht, was bei 2.x eingeführt wurde:
  • Erstellung ohne Parameter
  • Laden der Konfiguration per load(Reader)
  • Reader kann dann der StringReader genutzt werden.

Das wäre dann etwas wie:
Java:
String xmlConfig = "<whatever>...</whatever>";
XMLConfiguration config = new XMLConfiguration();
config.load(new StringReader(xmlConfig));

Bei 2.8 sind die Konstruktoren, die ein File oder Dateinamen nehmen, entfallen. Da geht es nur über das nachträgliche Laden. Aber aus load ist read geworden:
 

HRX

Mitglied
Nochmal danke.

Ich habe das jetzt alles in eine schöne eigene wrapper-Klasse umgesetzt.
Was mir nicht gelingt ist eine property der Art
"
<versions>
<version type="Auto">E</version>
"
in das Dokument zu schreiben.

Ein simples

addProperty("versions/version[@type='Hirn']","Keins");

erzeugt nichts

Ein
setProperty("versions/version[@type='Auto']","Keins");

ändert den Wert nicht auf "Keins"

Viele Grüße
 

KonradN

Super-Moderator
Mitarbeiter
Ich wollte damit gerade etwas herum spielen, aber diese Apache Library ist relativ "speziell" wie es mir scheint.

Das, was ich oben als Lösung gedacht hatte funktioniert nicht mit der 2.8er Version!
XMLConfiguration will zwingend eine Datei, die Dokumentation ist einfach zu mangelhaft. Der Versuch mit dem StringReader führt schlicht zu:
Java:
Exception in thread "main" org.apache.commons.configuration2.ex.ConfigurationException: Load operation not properly initialized! Do not call read(InputStream) directly, but use a FileHandler to load a configuration.
    at org.apache.commons.configuration2.XMLConfiguration.load(XMLConfiguration.java:829)
    at org.apache.commons.configuration2.XMLConfiguration.read(XMLConfiguration.java:804)
    at de.kneitzel.JavaApp.main(JavaApp.java:31)

Da ist dann ggf. noch mehr notwendig um da aus einem XML entsprechend Dinge zu laden.

Ist der Aufbau des XML Files fest? Wäre es eine Alternative, da auf diese Library einfach zu verzichten?

Optionen, die ich in Betracht ziehen würde:
  • Beliebiges XML - das kann sich also ändern und es interessiert nur ein gewisser Teil: Hier kann man direkt mit der XML Struktur arbeiten. Dann kann man die Nodes auswählen und löschen / verändern / hinzufügen.
  • festes XML - da würde ich eine marshalign / unmarshaling Lösung bauen - dann würde das Lesen / schreiben z.B. Jackson übernehmen und man hätte dann einfach eine Reihe Klassen, die die Daten abbilden und man kann dann sowas wie versions.add("Hirn", "Keins") machen, weil verseions eine Map<String,String> wäre mit key als Attribut type und value als Body. Und jeder Eintrag wäre ein version Element.

Aber da ist halt die Frage, was sind die Anforderungen? Ist eine alternative Lösung denkbar?
 

HRX

Mitglied
Ich wollte damit gerade etwas herum spielen, aber diese Apache Library ist relativ "speziell" wie es mir scheint.

Das, was ich oben als Lösung gedacht hatte funktioniert nicht mit der 2.8er Version!
XMLConfiguration will zwingend eine Datei, die Dokumentation ist einfach zu mangelhaft. Der Versuch mit dem StringReader führt schlicht zu:
Java:
Exception in thread "main" org.apache.commons.configuration2.ex.ConfigurationException: Load operation not properly initialized! Do not call read(InputStream) directly, but use a FileHandler to load a configuration.
    at org.apache.commons.configuration2.XMLConfiguration.load(XMLConfiguration.java:829)
    at org.apache.commons.configuration2.XMLConfiguration.read(XMLConfiguration.java:804)
    at de.kneitzel.JavaApp.main(JavaApp.java:31)

Da ist dann ggf. noch mehr notwendig um da aus einem XML entsprechend Dinge zu laden.

Ist der Aufbau des XML Files fest? Wäre es eine Alternative, da auf diese Library einfach zu verzichten?

Optionen, die ich in Betracht ziehen würde:
  • Beliebiges XML - das kann sich also ändern und es interessiert nur ein gewisser Teil: Hier kann man direkt mit der XML Struktur arbeiten. Dann kann man die Nodes auswählen und löschen / verändern / hinzufügen.
  • festes XML - da würde ich eine marshalign / unmarshaling Lösung bauen - dann würde das Lesen / schreiben z.B. Jackson übernehmen und man hätte dann einfach eine Reihe Klassen, die die Daten abbilden und man kann dann sowas wie versions.add("Hirn", "Keins") machen, weil verseions eine Map<String,String> wäre mit key als Attribut type und value als Body. Und jeder Eintrag wäre ein version Element.

Aber da ist halt die Frage, was sind die Anforderungen? Ist eine alternative Lösung denkbar?
Ich habe eben auch hrumgespielt, weil ich eigentlich "was neueres" verwenden will, also die 2.8er-Version.

Ich bekomme schon beim Aufruf des Construtors eine nebulöse Fehlermeldung.

Java:
 private XMLConfiguration xmlEntity = null;

....
    
      
       try
       {
           xmlEntity = new XMLConfiguration();

Code:
Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/commons/lang3/mutable/Mutable
    at org.apache.commons.configuration2@2.8.0/org.apache.commons.configuration2.BaseHierarchicalConfiguration.createNodeModel(BaseHierarchicalConfiguration.java:543)
    at org.apache.commons.configuration2@2.8.0/org.apache.commons.configuration2.BaseHierarchicalConfiguration.<init>(BaseHierarchicalConfiguration.java:73)
    at org.apache.commons.configuration2@2.8.0/org.apache.commons.configuration2.BaseHierarchicalConfiguration.<init>(BaseHierarchicalConfiguration.java:61)
    at org.apache.commons.configuration2@2.8.0/org.apache.commons.configuration2.XMLConfiguration.<init>(XMLConfiguration.java:222)
    at xmlcustom/xmlcustom.xmlEngine.createXmlEngineFromFile(xmlEngine.java:26)
    at xmlcustom/xmlcustom.main.main(main.java:39)
Caused by: java.lang.ClassNotFoundException: org.apache.commons.lang3.mutable.Mutable
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
    ... 6 more
 

HRX

Mitglied
Ich wollte damit gerade etwas herum spielen, aber diese Apache Library ist relativ "speziell" wie es mir scheint.

Das, was ich oben als Lösung gedacht hatte funktioniert nicht mit der 2.8er Version!
XMLConfiguration will zwingend eine Datei, die Dokumentation ist einfach zu mangelhaft. Der Versuch mit dem StringReader führt schlicht zu:
Java:
Exception in thread "main" org.apache.commons.configuration2.ex.ConfigurationException: Load operation not properly initialized! Do not call read(InputStream) directly, but use a FileHandler to load a configuration.
    at org.apache.commons.configuration2.XMLConfiguration.load(XMLConfiguration.java:829)
    at org.apache.commons.configuration2.XMLConfiguration.read(XMLConfiguration.java:804)
    at de.kneitzel.JavaApp.main(JavaApp.java:31)

Da ist dann ggf. noch mehr notwendig um da aus einem XML entsprechend Dinge zu laden.

Ist der Aufbau des XML Files fest? Wäre es eine Alternative, da auf diese Library einfach zu verzichten?

Optionen, die ich in Betracht ziehen würde:
  • Beliebiges XML - das kann sich also ändern und es interessiert nur ein gewisser Teil: Hier kann man direkt mit der XML Struktur arbeiten. Dann kann man die Nodes auswählen und löschen / verändern / hinzufügen.
  • festes XML - da würde ich eine marshalign / unmarshaling Lösung bauen - dann würde das Lesen / schreiben z.B. Jackson übernehmen und man hätte dann einfach eine Reihe Klassen, die die Daten abbilden und man kann dann sowas wie versions.add("Hirn", "Keins") machen, weil verseions eine Map<String,String> wäre mit key als Attribut type und value als Body. Und jeder Eintrag wäre ein version Element.

Aber da ist halt die Frage, was sind die Anforderungen? Ist eine alternative Lösung denkbar?
Ich überlege noch, was notwendig ist und was weggelassen werden kann.
Grundsätzlich strebe ich immer Lösungen an, die jeden Anwendungsfall abdecken.
VG
 

KonradN

Super-Moderator
Mitarbeiter
Wie bindest Du die Abhängigkeiten ein? Ich empfehle da immer Maven (oder Gradle), da dort Abhängigkeiten auch transitiv aufgelöst werden.

commons-configuration2 hat als Abhängigkeiten:
  • commons-lang3
  • commons-text
  • commons-logging

Wenn Du Abhängigkeiten manuell hinzu fügst, dann musst Du diese Abhängigkeiten mit aufnehmen.
 

HRX

Mitglied
Wie bindest Du die Abhängigkeiten ein? Ich empfehle da immer Maven (oder Gradle), da dort Abhängigkeiten auch transitiv aufgelöst werden.

commons-configuration2 hat als Abhängigkeiten:
  • commons-lang3
  • commons-text
  • commons-logging

Wenn Du Abhängigkeiten manuell hinzu fügst, dann musst Du diese Abhängigkeiten mit aufnehmen.
Danke, das hat geholfen :)
 

HRX

Mitglied
Also, mit ver 2.8 eine xml-Datei einlesen ist nicht gerade ein Selbstläufer.

Java:
public static xmlEngine createXmlEngineFromFile(String Datei)
{
  XMLConfiguration xmlEntity = null;
  try
  {
           xmlEntity = new XMLConfiguration();
           try
           {
             xmlEntity.read(new InputStreamReader(new FileInputStream(Datei)));
           }
           catch (IOException e)
           {
               System.out.println(e.toString());
           }
      ...

gibt folgende Fehlermeldung :
Code:
org.apache.commons.configuration2.ex.ConfigurationException: Load operation not properly initialized! Do not call read(InputStream) directly, but use a FileHandler to load a configuration.

Erratisch, alle Links zum Thema sind es auch..
:-(
 

KonradN

Super-Moderator
Mitarbeiter
Ja, das war auch etwas meine Erfahrung. Ich mag die Apache Libraries auch nicht. Zumindest macht mir die Arbeit mit der Dokumentation und den Libraries keinen Spass und ich neige dazu, diese Libraries wo immer möglich zu meiden. Und leider habe ich mit der Library keine Erfahrungen und nachdem ich auf diese Exception gestoßen bin, war meine Motivation bei Null und mein (Vor)urteil zu Apache Libraries bestätigt.

Daher meine Frage, ob es diese Library sein muss und so.
 

HRX

Mitglied
Mir ist es egal, welche Library den Erfolg bringt, so tief bin ich nicht in Java drinnen,
dass ich Vorlieben entwickle. Komischerweise sind die apache libraries immer recht weit oben in den Suchergebnissen :)
 

KonradN

Super-Moderator
Mitarbeiter
Da wäre dann die wichtige Frage, was denn die genauen Vorgaben sind.

Wenn es wirklich nur um das Speichern einer Konfiguration geht, dann wären andere Wege üblicher:
  • Properties - Man hat da einfache Textdateien mit key = value Zeilen. Was man da braucht ist dann auch schon Bestandteil vom Java Framework
  • sehr oft finden sich JSON Dateien, die man dann in der Regel einfach mit einer Library wie jackson oder gson einliest / schreibt
  • Wenn es um User Settings gehen sollte: Da wäre die Preference API von Java ein üblicher Weg.
  • Was man teilweise auch findet: YAML - das ist dann ähnlich zu JSON (Das ist aber mehr etwas für Leute, Python mögen :) )

Viele Frameworks haben da auch Lösungen, die etwas mehr können. Spring Framework z.B. das Konfigurationen an diversen Stellen sucht und in diversen Formaten lesen kann.
 

HRX

Mitglied
Da wäre dann die wichtige Frage, was denn die genauen Vorgaben sind.

Wenn es wirklich nur um das Speichern einer Konfiguration geht, dann wären andere Wege üblicher:
  • Properties - Man hat da einfache Textdateien mit key = value Zeilen. Was man da braucht ist dann auch schon Bestandteil vom Java Framework
  • sehr oft finden sich JSON Dateien, die man dann in der Regel einfach mit einer Library wie jackson oder gson einliest / schreibt
  • Wenn es um User Settings gehen sollte: Da wäre die Preference API von Java ein üblicher Weg.
  • Was man teilweise auch findet: YAML - das ist dann ähnlich zu JSON (Das ist aber mehr etwas für Leute, Python mögen :) )

Viele Frameworks haben da auch Lösungen, die etwas mehr können. Spring Framework z.B. das Konfigurationen an diversen Stellen sucht und in diversen Formaten lesen kann.
Die Vorgaben sind, dass eine Konfiguration basierend auf xml (besser: xml-Datei) existiert, da kann ich nichts ändern,
der Herstelller wird das nicht für mich anders implementieren.

Die xml wird ausgewertet im Sinnne von:

o Existenz von Werten
o Werte auslesen.
o Werte Ändern
o Werte hinzufügen.

Mir ist bei xml nie so ganz klar, wie die Nomenklatur ist, Nodes, Attribut, Wert

Für mich ist das ein Wert -> #808080):

<colors>
<background>#808080</background>
</colors>

VG

PS.: Notfalls nehme ich einfach wieder XMLConfiguration 1.xy, das ist wesentlich logischer,
für das "importieren" von vorgegebenem xml (Datei,String) ist da nicht so viel zu machen und es funktioniert dann auch gleich :)
 

HRX

Mitglied
So, der Vollständigkeit halber.

Gegeben:

o Java configuration 1.10

XML:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<settings>
<versions>
<version type="FARBE">Blau</version>
<version type="FORM">RUND</version>
<version type="PREIS">500</version>
</versions>
</settings>



Ändern einer Version-Zeile (hier: 1. Zeile):

Java:
setProperty("versions/version[@type='FARBE']","ROT");

Neuer Eintrag:
o gewünscht : <version type="NAME">WILLY</version>

Neue Methode :

Java:
import org.apache.commons.configuration.*;
import org.apache.commons.configuration.tree.xpath.XPathExpressionEngine;
import org.apache.commons.configuration.ConfigurationException;

..
  XMLConfiguration  xmlEntity= new XMLConfiguration();
  xmlEntity.setExpressionEngine(new XPathExpressionEngine());
..

public boolean addPropertyWithAttr(String propertyStart,String newEntry,String value,String attribute,String attributeVal)
 {
       xmlEntity.addProperty(propertyStart+" "+ newEntry,value);
       xmlEntity.addProperty(propertyStart+"/"+ newEntry+"[last()]"+" @"+attribute,attributeVal);
 
       String chk = xmlEntity.getString(propertyStart+"/"+newEntry+"[@"+attribute+"='"+attributeVal+"']");
 
       if (chk != null)
          return(true);
       else
       {
         return(false);
       }
 }

Aufruf:

Java:
addPropertyWithAttr("versions","version","WILLY","type","NAME");

Ergebnis:

XML:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  <settings>
    <versions>
         <version type="FARBE">Blau</version>
        <version type="FORM">RUND</version>
        <version type="PREIS">500</version>
        <version type="NAME">WILLY</version>
    </versions>
</settings>

Das ist bestimmt nicht vollständig, für meine Zwecke reicht es und kann für andere Ideen als Hilfe fungieren.
Das Beispiel ist natürlich irgendwie sinnfrei, da ich nicht unbedingt verraten will, wofür ich meine Methode verwende,
Betriebsgeheimnis halt.

Referenz: http://repository.transtep.com/repo...uration-1.6/docs/userguide-1.2/howto_xml.html



Grüßle :cool:
 
Zuletzt bearbeitet:

Ähnliche Java Themen


Oben