2009-04-07 7 views
33

Bei der Verarbeitung von XML mit Standard-DOM ist die Reihenfolge der Attribute nach der Serialisierung nicht gewährleistet. Endlich habe ich festgestellt, dass ich die Standard Java XML Transform API benutze, um die Ausgabe zu serialisieren.Reihenfolge der XML-Attribute nach DOM-Verarbeitung

Allerdings muss ich eine Bestellung behalten. Ich würde gerne wissen, ob es eine Möglichkeit in Java gibt, die ursprüngliche Reihenfolge von Attributen einer XML-Datei mittels DOM-API zu behalten, oder irgendeine Art, die Bestellung zu erzwingen (vielleicht mithilfe einer alternativen Serialisierungs-API, die dies ermöglicht) Art von Eigentum). In meinem Fall reduziert sich die Verarbeitung, um den Wert einiger Attribute (nicht alle) einer Sequenz derselben Elemente mit einer Reihe von Attributen zu ändern und möglicherweise ein paar weitere Elemente einzufügen.

Gibt es einen "einfachen" Weg oder muss ich mein eigenes XSLT-Transformations-Stylesheet definieren, um die Ausgabe festzulegen und die gesamte XML-Eingabedatei zu ändern?

Update Ich muss all Ihre Antworten danken. Die Antwort scheint jetzt offensichtlicher als ich erwartet hatte. Ich habe der Reihenfolge der Attribute nie Beachtung geschenkt, da ich sie vorher nie gebraucht hatte.

Der Hauptgrund für eine Attributreihenfolge ist, dass die resultierende XML-Datei nur anders aussieht. Das Ziel ist eine Konfigurationsdatei, die Hunderte von Alarmen enthält (jeder Alarm wird durch eine Reihe von Attributen definiert). Diese Datei hat im Laufe der Zeit nur wenige Änderungen, aber es ist praktisch, sie geordnet zu halten, denn wenn wir etwas modifizieren müssen, wird es von Hand bearbeitet. Von Zeit zu Zeit benötigen einige Projekte leichte Modifikationen dieser Datei, z. B. das Setzen eines der Attribute auf einen kundenspezifischen Code.

Ich habe gerade eine kleine Anwendung entwickelt, um Originaldateien (die in allen Projekten verwendet werden) mit bestimmten Teilen jedes Projekts zusammenzuführen (den Wert einiger Attribute zu ändern), sodass die projektspezifische Datei die Aktualisierungen der Basisdatei erhält (neuer Alarm) Definitionen oder einige Attributwerte Bugfixes). Meine Hauptmotivation, geordnete Attribute zu verlangen, besteht darin, die Ausgabe der Anwendung gegen die Originaldatei mit Hilfe eines Textvergleichstools (wie Winmerge) überprüfen zu können. Wenn das Format (hauptsächlich die Reihenfolge der Attribute) gleich bleibt, können die Unterschiede leicht erkannt werden.

Ich dachte wirklich, dass dies möglich war, da XML-Behandlungsprogramme, wie XML-Spion, Sie XML-Dateien bearbeiten und einige Reihenfolge (Rastermodus) anwenden können. Vielleicht ist meine einzige Wahl, eines dieser Programme zu verwenden manuell ändern Sie die Ausgabedatei.

+0

* Warum * Sie einen Auftrag halten müssen? Die Anforderung impliziert, dass Sie den XML-Text mit Tools verarbeiten, die nicht für XML erstellt wurden. Ist das der Fall? – Tomalak

+0

Die Lösung für Ihr angegebenes Problem besteht darin, ein Programm zu schreiben, das die zu vergleichenden Dateien vor dem Vergleich vorverarbeitet. Ein solches Programm würde die Attribute in eine kanonische Reihenfolge bringen. –

+5

Commander @Tomalak, ich verarbeite XML-Text mit Tools, die nicht für XML gemacht wurden: meine Augen. Xml ist auch ein von Menschen lesbares Format. –

Antwort

20

Leider sagen, aber die Antwort ist subtiler als „Nein kann man nicht“ oder „Warum müssen Sie dies tun, in erster Linie?“.

Die kurze Antwort ist "DOM wird Ihnen nicht erlauben, das zu tun, aber SAX wird".

Dies liegt daran, dass DOM sich nicht um die Reihenfolge der Attribute kümmert, da sie für den Standard bedeutungslos ist und die Info schon verloren ist, wenn das XSL den Eingabestrom erhält. Die meisten XSL-Engine behält die Reihenfolge der Eingabestromattribute (z. B. Xalan-C (außer in einem Fall) oder Xalan-J (immer)) ordnungsgemäß bei. Vor allem, wenn Sie <xsl:copy*> verwenden.

Fälle, in denen die Attributreihenfolge nicht eingehalten wird, sind meines Wissens bestechend. - Wenn der Eingangsstrom ein DOM - Xalan-C., Wenn Sie Ihr Ergebnis-Baum-Tags wahrsten Sinne des Wortes ein (zB <elem att1={@att1} .../>

Hier ist ein Beispiel mit SAX, für die Aufzeichnung (DTD Hemmung als auch nagende)

SAXParserFactory spf = SAXParserFactoryImpl.newInstance(); 
spf.setNamespaceAware(true); 
spf.setValidating(false); 
spf.setFeature("http://xml.org/sax/features/validation", false); 
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false); 
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); 
SAXParser sp = spf.newSAXParser() ; 
Source src = new SAXSource (sp.getXMLReader(), new InputSource(input.getAbsolutePath())) ; 
String resultFileName = input.getAbsolutePath().replaceAll(".xml$", ".cooked.xml") ; 
Result result = new StreamResult(new File (resultFileName)) ; 
TransformerFactory tf = TransformerFactory.newInstance(); 
Source xsltSource = new StreamSource(new File (COOKER_XSL)); 
xsl = tf.newTransformer(xsltSource) ; 
xsl.setParameter("srcDocumentName", input.getName()) ; 
xsl.setParameter("srcDocumentPath", input.getAbsolutePath()) ; 

xsl.transform(src, result); 

ich auch an der Absicht vieler Pessimisten darauf hin möchte, dass es sind Fälle, in denen Attribut um tut Materie.

Regressionstests ist eine offensichtliche ca se. Wer zur Optimierung von nicht ganz so gut geschriebenen XSL aufgerufen wurde, weiß, dass Sie normalerweise sicherstellen wollen, dass "neue" Ergebnisbäume den "alten" ähnlich oder identisch sind. Und wenn der Ergebnisbaum ungefähr eine Million Zeilen umfasst, erweisen sich XML-Vergleichswerkzeuge als zu unhandlich ... In diesen Fällen ist die Beibehaltung der Attributreihenfolge eine große Hilfe.

hoffe, das hilft ;-)

+1

+1, aber Ihr Beispiel für Regressionstests ist ein "red herring". Die Lösung besteht darin, dass das Regressionstool zuerst die XML-Datei vor dem Vergleich in eine kanonische Reihenfolge konvertiert. –

+4

@JohnSaunders Auf der anderen Seite ist eines der Schönheiten von XML, dass Menschen es lesen können, und zumindest in LtoR-Ländern neigen wir dazu, nach wichtigen Dingen in Richtung L zu suchen, mit weniger wichtigen Dingen in R. Idealerweise wäre es schön, die Reihenfolge beizubehalten, wenn das XML erstellt wird, da der Ersteller die Attributreihenfolge für Menschen als signifikant angesehen haben könnte. Zumindest sollte dies eine Option für das Schreiber- oder Dokumentobjekt sein. – MushyMiddle

+0

Da XML jedoch die Reihenfolge der Attribute nicht berücksichtigt, wäre das nicht sehr sinnvoll. –

2

Sie sollten wirklich keine Reihenfolge einhalten müssen. Soweit ich weiß, berücksichtigt kein Schema die Attributreihenfolge bei der Validierung eines XML-Dokuments. Es hört sich an, als würde alles, was XML verarbeitet, am anderen Ende kein geeignetes DOM verwenden, um die Ergebnisse zu parsen.

Ich nehme an, eine Option wäre, das Dokument mit String-Erstellung manuell aufzubauen, aber ich empfehle dringend, dass.

23

Siehe Abschnitt 3.1 der XML-Empfehlung. Es heißt: "Beachten Sie, dass die Reihenfolge der Attributspezifikationen in einem Start-Tag oder einem leeren Element-Tag nicht signifikant ist."

Wenn eine Software erfordert, dass Attribute in einem XML-Element in einer bestimmten Reihenfolge angezeigt werden, verarbeitet diese Software XML nicht, sondern verarbeitet Text, der oberflächlich wie XML aussieht. Es muss behoben werden.

Wenn es nicht repariert werden kann und Sie Dateien erzeugen müssen, die seinen Anforderungen entsprechen, können Sie die XML-Standardwerkzeuge nicht zuverlässig zur Erstellung dieser Dateien verwenden. Zum Beispiel könnten Sie versuchen (wie Sie vorschlagen), XSLT zu verwenden, um Attribute in einer definierten Reihenfolge zu erzeugen, z.:

<test> 
    <xsl:attribute name="foo"/> 
    <xsl:attribute name="bar"/> 
    <xsl:attribute name="baz"/> 
</test> 

nur, dass der XSLT-Prozessor diese finden aussendet:

<test bar="" baz="" foo=""/> 

weil das DOM, dass der Prozessor Befehle verwendet von Tag-Namen Attribute alphabetisch. (Das ist allgemeines aber nicht allgemeines Verhalten unter XML DOMs.)

Aber ich möchte etwas betonen. Wenn eine Software die XML-Empfehlung in einer Hinsicht verletzt, verletzt sie sie wahrscheinlich in anderer Hinsicht. Wenn es bricht, wenn Sie es Attribute in der falschen Reihenfolge einspeisen, wird es wahrscheinlich auch unterbrochen, wenn Sie Attribute mit einfachen Anführungszeichen begrenzen, oder wenn die Attributwerte Zeichenentitäten enthalten, oder eines der anderen Dinge, die die XML-Empfehlung als XML-Dokument angibt kann tun, dass der Autor dieser Software wahrscheinlich nicht darüber nachgedacht hat.

6

Es ist nicht möglich zu betonen, was Robert Rossney gerade gesagt hat, aber ich werde es versuchen. ;-)

Der Vorteil von International Standards ist, dass, wenn jeder ihnen folgt, das Leben gut ist. All unsere Software kommt friedlich miteinander aus.

XML muss einer der wichtigsten Standards sein, die wir haben. Es ist die Grundlage von "alten Web" Sachen wie SOAP, und immer noch 'Web 2.0' Sachen wie RSS und Atom. Aufgrund klarer Standards ist XML in der Lage, zwischen verschiedenen Plattformen zu arbeiten. Wenn wir nach und nach auf XML verzichten, geraten wir in eine Situation, in der ein XML-Produzent nicht davon ausgehen kann, dass ein Konsument von XML seinen Inhalt konsumieren kann. Dies hätte einen katastrophalen Einfluss auf die Industrie.

Wir sollten sehr stark zurückdrängen, auf jeden, der Code schreibt, der XML nicht gemäß dem Standard verarbeitet. Ich verstehe, dass es in diesen wirtschaftlichen Zeiten eine Abneigung gibt, Kunden und Geschäftspartner zu verärgern, indem man "Nein" sagt. Aber in diesem Fall denke ich, dass es das wert ist. Wir wären finanziell viel schlechter in der Lage, wenn wir XML für jeden Geschäftspartner in Handarbeit erstellen müssten.

Aktivieren Sie also keine Unternehmen, die XML nicht verstehen. Senden Sie ihnen den Standard, und markieren Sie die entsprechenden Zeilen. Sie müssen aufhören zu denken, dass XML nur Text mit spitzen Klammern ist. Es verhält sich einfach nicht wie ein Text mit spitzen Klammern.

Es ist nicht wie es eine Entschuldigung dafür gibt. Selbst die kleinsten eingebetteten Geräte können in ihnen voll funktionsfähige XML-Parser-Implementierungen enthalten. Ich habe noch keinen guten Grund gehört, Standard-XML nicht parsen zu können, auch wenn man sich eine voll funktionsfähige DOM-Implementierung nicht leisten kann.

1

Robert Rossney sagte es gut: Wenn Sie sich auf die Reihenfolge der Attribute verlassen, verarbeiten Sie nicht wirklich XML, sondern etwas, das wie XML aussieht.

Ich kann mir mindestens zwei Gründe vorstellen, warum Sie sich um die Attributbestellung kümmern sollten. Es können andere sein, aber zumindest für diese beiden Alternativen kann ich vorschlagen:

  1. Sie verwenden mehrere Instanzen von Attributen mit dem gleichen Namen:

    <foo myAttribute="a" myAttribute="b" myAttribute="c"/> 
    

    Dies ist einfach nur ungültige XML; ein DOM-Prozessor wird wahrscheinlich alle bis auf einen dieser Werte löschen - wenn er das Dokument überhaupt verarbeitet.Statt dessen wollen Sie untergeordnete Elemente verwenden:

    <foo> 
        <myChild="a"/> 
        <myChild="b"/> 
        <myChild="c"/> 
    </foo> 
    
  2. Sie gehen davon aus, dass irgendeine Art von Unterscheidung auf das Attribut gilt (en), die zuerst kommen. Machen Sie dies explizit, entweder durch andere Attribute oder durch untergeordnete Elemente. Zum Beispiel:

    <foo attr1="a" attr2="b" attr3="c" theMostImportantAttribute="attr1" /> 
    
+2

In meinem Fall schreibe ich ein Migrationsskript, das eine XML-Konfiguration manipuliert, die im VCS gespeichert ist. Das VCS-Diff zeigt sinnlose Änderungen (Änderung der Attributreihenfolge) sowie sinnvolle Änderungen (was das Programm geändert hat). Es wäre schön, nur sinnvolle Veränderungen zu zeigen. Auch (obwohl dies kein Problem ist, das ich habe) werden Pseudo-Merge-Konflikte auftreten, wenn mehrere Leute diese Art von Dingen gemacht haben und ihre XML-Serialisierer nicht modifizierte Attribute in verschiedenen Ordnungen geschrieben haben. –

+0

Manchmal schreibt man ein Skript für Software/Konfigurationsdateien von Drittanbietern. XML ist dir aufgezwungen. – kierans

+1

@AdrianSmith: Ihr Szenario kann verarbeitet werden, indem Sie beide Seiten des Vergleichs im Voraus mit einem Skript oder Stylesheet verarbeiten, das das XML in einer kanonischen Reihenfolge ausgibt. Ich habe dies getan, um SQL Server Integration Services .dtsx-Dateien zu vergleichen, die weit schlimmere Probleme haben, die die Reihenfolge bestimmen. Diese Dateien ändern sich unter anderem, indem Sie sie einfach im Design-Tool öffnen. –

9

XML Kanonisierung Ergebnisse in einer konsistenten Attribut Bestellung, in erster Linie eine zu erlauben, eine Signatur über einige oder alle der XML zu überprüfen, obwohl es andere mögliche Verwendungen sind. Dies kann Ihren Zwecken entsprechen.

+0

Obwohl das Problem nicht mehr auf meine aktuelle Situation zutrifft, danke ich Ihrer Antwort. In naher Zukunft könnte es nützlich sein –

+0

Dies ist die Antwort für Leute, die XML in automatisierten Tests und Diffs vergleichen wollen. Deshalb wurde die Kanonisierung entwickelt. Es macht eine Menge Potential [Änderungen] (https://www.ibm.com/developerworks/library/x-c14n/index.html) zu dem Dokument, aber sie haben mich nicht sehr beeinflusst und ich habe sie behalten. Ich habe mein c14n mit Python 'lxml', voll funktionsfähiges Snippet unter https://stackoverflow.com/questions/22959577/python-exclusive-xml-canonicalization-xml-exc-c14n/22960033#22960033. – Noumenon

0

Ich denke, ich kann für das Interessieren für Attribut, um einige gültige Rechtfertigungen finden:

  • Sie Menschen erwarten können manuell zu haben, zu lesen, diagnostizieren oder die XML-Daten ein oder andere Mal bearbeiten; Lesbarkeit wäre in diesem Fall wichtig, und eine konsistente und logische Anordnung der Attribute hilft dabei;
  • Möglicherweise müssen Sie mit einem Tool oder einem Dienst kommunizieren, der (irrtümlicherweise irrtümlich) sich um den Auftrag kümmert; Den Anbieter zu bitten, seinen Code zu korrigieren, ist möglicherweise keine Option: Versuchen Sie, dies von einer Regierungsbehörde zu verlangen, während die Frist Ihres Benutzers für die elektronische Lieferung einer Reihe von Steuerdokumenten immer näher rückt!

Es scheint wie Alain Pannetier's solution ist der Weg zu gehen.

Sie können auch einen Blick auf DecentXML werfen; Es gibt Ihnen vollständige Kontrolle darüber, wie das XML formatiert ist, obwohl es nicht DOM-kompatibel ist. Besonders nützlich, wenn Sie manuell bearbeitetes XML ändern möchten, ohne die Formatierung zu verlieren.

+0

Ihre Menschen sollten gelehrt werden, dass die Reihenfolge keine Rolle spielt. Und, ja, wenn Ihre Regierung die Art ist, die abweichende Software-Ingenieure zurücknimmt und sie erschießt, dann sagen Sie nicht nein. Aber versuchen Sie, einen Weg zu finden, uns zu sagen, welche Regierung es ist, also wissen wir für die Zukunft. –

+2

Tut mir leid, @John Saunders. Menschen müssen nicht durch Software "unterrichtet" werden, Software muss die Bedürfnisse der Menschen erfüllen. Wenn Sie Benutzer haben, die es nützlich finden können, Attribute in einer bestimmten Reihenfolge zu überprüfen (vielleicht, um einen 15min-Job in 2h nicht zu machen ...), müssen Sie das tun oder Sie sind ein inkompetenter Ingenieur. Die Menschen kommen zuerst. – Renascienza

+0

@ren Ich habe nicht gesagt, dass sie von Software gelehrt werden müssen. Ich sagte, sie müssten über Software unterrichtet werden. XML funktioniert so, wie es funktioniert, nicht so, wie uninformierte Leute es sich vorstellen. Eine konforme XML-Implementierung kann die Attribute in beliebiger Reihenfolge darstellen und trotzdem korrekt sein. In diesem Fall verwirrte das OP die Benutzeroberfläche eines Tools für das Verhalten des Standards. Er brauchte ein Vergleichswerkzeug, das XML verstand. –

1

Ich hatte das gleiche genaue Problem. Ich wollte XML-Attribute ändern, wollte aber die Reihenfolge wegen diff beibehalten. Ich habe StAX verwendet, um dies zu erreichen. Sie müssen XMLStreamReader und XMLStreamWriter (die Cursor-basierte Lösung) verwenden. Wenn Sie einen Ereignistyp START_ELEMENT erhalten, behält der Cursor den Index der Attribute bei. Daher können Sie entsprechende Änderungen vornehmen und sie in die Ausgabedatei "in Reihenfolge" schreiben.

Schauen Sie sich diese article/discussion. Sie können sehen, wie die Attribute der Startelemente in der Reihenfolge gelesen werden.

+0

Sie können die Reihenfolge der Attribute mit vtd-xml und nur mit vtd-xml beibehalten –

-1

Ich habe ein ziemlich ähnliches Problem. Ich muss immer zuerst das gleiche Attribut haben. Beispiel:

<h50row a="1" xidx="1" c="1"></h50row> 
<h50row a="2" b="2" xidx="2"></h50row> 

<h50row xidx="1" a="1" c="1"></h50row> 
<h50row xidx="2" a="2" b="2"></h50row> 

werden muss, fand ich eine Lösung mit einem regex:

test = "<h50row a=\"1\" xidx=\"1\" c=\"1\"></h50row>"; 
test = test.replaceAll("(<h5.*row)(.*)(.xidx=\"\\w*\")([^>]*)(>)", "$1$3$2$4$5"); 

Hoffe, dass Sie diese nützlich finden

0

Sie noch dies die Verwendung tun können Standard DOM und Transformation API mit einer schnellen und schmutzigen Lösung wie der, die ich bin Ritzen:

Wir wissen, dass die Transformations-API-Lösung die Attribute alphabetisch sortiert. Sie können den Namen der Attribute einige leicht zu entfernende Zeichenfolgen voranstellen, damit sie in der gewünschten Reihenfolge ausgegeben werden. Einfache Präfixe wie "a_" "b_" usw. sollten in den meisten Situationen ausreichen und können leicht aus der Ausgabe xml entfernt werden, indem ein Einstrich-Regex verwendet wird.

Wenn Sie ein XML laden und erneut speichern und die Reihenfolge der Attribute beibehalten möchten, können Sie das gleiche Prinzip verwenden, indem Sie zunächst die Attributnamen im Eingabe-XML-Text ändern und dann in ein Document-Objekt analysieren. Auch diese Änderung basiert auf einer Textverarbeitung des XML. Dies kann schwierig sein, kann aber auch durch das Erkennen von Elementen und deren Attributen erfolgen, wiederum unter Verwendung von Regex. Beachten Sie, dass dies eine schmutzige Lösung ist. Es gibt viele Fallstricke beim selbstständigen Analysieren von XML selbst für so etwas Einfaches. Seien Sie also vorsichtig, wenn Sie sich dazu entscheiden, dies zu implementieren.

0

Art der Arbeiten ...

package mynewpackage; 

// for the method 
import java.lang.reflect.Constructor; 
import java.util.ArrayList; 
import java.util.Arrays; 
import java.util.Comparator; 
import java.util.List; 
import org.w3c.dom.Element; 
import org.w3c.dom.Node; 
import org.w3c.dom.NodeList; 

// for the test example 
import org.xml.sax.InputSource; 
import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import java.io.StringReader; 
import org.w3c.dom.Document; 
import java.math.BigDecimal; 

public class NodeTools { 
    /** 
    * Method sorts any NodeList by provided attribute. 
    * @param nl NodeList to sort 
    * @param attributeName attribute name to use 
    * @param asc true - ascending, false - descending 
    * @param B class must implement Comparable and have Constructor(String) - e.g. Integer.class , BigDecimal.class etc 
    * @return 
    */ 
    public static Node[] sortNodes(NodeList nl, String attributeName, boolean asc, Class<? extends Comparable> B) 
    {   
     class NodeComparator<T> implements Comparator<T> 
     { 
      @Override 
      public int compare(T a, T b) 
      { 
       int ret; 
       Comparable bda = null, bdb = null; 
       try{ 
        Constructor bc = B.getDeclaredConstructor(String.class); 
        bda = (Comparable)bc.newInstance(((Element)a).getAttribute(attributeName)); 
        bdb = (Comparable)bc.newInstance(((Element)b).getAttribute(attributeName)); 
       } 
       catch(Exception e) 
       { 
        return 0; // yes, ugly, i know :) 
       } 
       ret = bda.compareTo(bdb); 
       return asc ? ret : -ret; 
      } 
     } 

     List<Node> x = new ArrayList<>(); 
     for(int i = 0; i < nl.getLength(); i++) 
     { 
      x.add(nl.item(i)); 
     } 
     Node[] ret = new Node[x.size()]; 
     ret = x.toArray(ret); 
     Arrays.sort(ret, new NodeComparator<Node>()); 
     return ret; 
    }  

    public static void main(String... args) 
    { 
     DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder builder; 
     String s = "<xml><item id=\"1\" price=\"100.00\" /><item id=\"3\" price=\"29.99\" /><item id=\"2\" price=\"5.10\" /></xml>"; 
     Document doc = null; 
     try 
     { 
      builder = factory.newDocumentBuilder(); 
      doc = builder.parse(new InputSource(new StringReader(s))); 
     } 
     catch(Exception e) { System.out.println("Alarm "+e); return; } 

     System.out.println("*** Sort by id ***"); 
     Node[] ret = NodeTools.sortNodes(doc.getElementsByTagName("item"), "id", true, Integer.class); 

     for(Node n: ret) 
     { 
      System.out.println(((Element)n).getAttribute("id")+" : "+((Element)n).getAttribute("price")); 
     } 

     System.out.println("*** Sort by price ***"); 
     ret = NodeTools.sortNodes(doc.getElementsByTagName("item"), "price", true, BigDecimal.class); 
     for(Node n: ret) 
     { 
      System.out.println(((Element)n).getAttribute("id")+" : "+((Element)n).getAttribute("price")); 
     } 
    } 
} 

In meinem einfachen Test druckt:

*** Sort by id *** 
1 : 100.00 
2 : 5.10 
3 : 29.99 
*** Sort by price *** 
2 : 5.10 
3 : 29.99 
1 : 100.00 
+0

Nicht wirklich mit dieser Frage verbunden.Der Typ muss keine Elemente, sondern Attribute innerhalb von Elementen bestellen. – Renascienza