2016-10-10 24 views
0

Ich analysiere ein einfaches XML und versuche, auf die nodeNames zuzugreifen. In einigen Varianten dieses XML haben einige nodeNames ein Namensraum-Präfix "mets:". Ich versuche, alle "fptr" -Elemente zu vergleichen, egal ob sie ein Mets-Präfix haben oder nicht.getNodeName, getLocalName gibt keine erwarteten Werte zurück

Hier ist ein Beispiel für die xml, sowohl einfache fptr Elemente und einige mit Präfix enthält:

<mets:structMap xmlns:mets="http://www.loc.gov/METS/" xmlns="http://www.loc.gov/METS/" TYPE="logical" ID="DTL1"> 
    <div ORDER="1" LABEL="Alle Scans" TYPE="first level" ID="DTL2"> 
     <div ORDER="1" LABEL="1" TYPE="Seite" ID="DTL3"> 
      <mets:fptr FILEID="FID00000020" ID="DTL21"/> 
     </div> 
     <div ORDER="2" LABEL="2" TYPE="Seite" ID="DTL4"> 
      <mets:fptr FILEID="FID00000021" ID="DTL22"/> 
     </div> 
    </div> 

    <div ORDER="1" LABEL="Hauptdokument - pdf" TYPE="entry" ID="DTL5"> 
     <fptr FILEID="FID1a" ID="DTL11"/> 
    </div> 
</mets:structMap> 

Und hier ist eine einfache Analyseroutine, die das Element sollte Namen und ns-Präfix aller Elemente ausdrucken:

package at.ac.onb.zid.dtlcontent.test; 

import java.io.File; 
import java.io.IOException; 

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
import javax.xml.parsers.ParserConfigurationException; 

import org.w3c.dom.Document; 
import org.w3c.dom.Element; 
import org.w3c.dom.Node; 
import org.w3c.dom.NodeList; 
import org.xml.sax.SAXException; 

public class structMapTest { 
    public static void main(String args[]) throws ParserConfigurationException, SAXException, IOException { 
     File fXmlFile = new File("src/test/resources/teststructmap.xml"); 
     DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); 
     DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); 
     Document doc = dBuilder.parse(fXmlFile); 
     doc.getDocumentElement().normalize(); 

     NodeList elemList = doc.getElementsByTagName("*"); 
     for(int i = 0; i<elemList.getLength();i++) { 
      Node n = elemList.item(i); 
      System.out.println("nodeName=" + n.getNodeName()); 

      if(n instanceof Element) { 
       Element e = (Element) n; 
       String eID = e.getAttribute("ID"); 
       String nsPrefix = e.getPrefix(); 
       String eLN = e.getLocalName(); 
       String eNSURI = e.getNamespaceURI(); 

       System.out.println(" ID=" + eID); 
       System.out.println(" prefix=" + nsPrefix); 
       System.out.println(" localName=" + eLN); 
       System.out.println(" nsURI=" + eNSURI); 
       System.out.println(""); 
      } 
     } 
    } 
} 

Dies ist, was es aber druckt:

nodeName=mets:structMap 
    ID=DTL1 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=div 
    ID=DTL2 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=div 
    ID=DTL3 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=mets:fptr 
    ID=DTL21 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=div 
    ID=DTL4 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=mets:fptr 
    ID=DTL22 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=div 
    ID=DTL5 
    prefix=null 
    localName=null 
    nsURI=null 

nodeName=fptr 
    ID=DTL11 
    prefix=null 
    localName=null 
    nsURI=null 

A lle Präfixwerte sind null. Ich erwartete, dass die ersten beiden fptr-Präfixe (von ID = DTL21 und DTL22) "getroffen" werden.

Gleiches mit dem localName: Ich erwartete, dass alle fptr-localNames "fptr" sind, stattdessen sind sie alle null. Ähnlich dem Namespace-URI.

Was fehlt mir hier?

Antwort

1

Stellen Sie sicher, dass Sie dbFactory.setNamespaceAware(true); festlegen, bevor Sie versuchen, mit XML mit Namespaces auf sinnvolle Weise zu arbeiten.

+0

Vielen Dank. Ich vermutete so etwas, wusste aber nicht einmal, wo ich anfangen sollte ... das löste es. – jackthehipster

1

XML-Namespaces sind durchaus sinnvoll, genauso wie viel von XML-Design und tatsächlich wie viel von XML-Design kann ein echter Schmerz im Arsch sein, wenn es direkt in Code zu tun. In Ihrem Beispiel sind sowohl die vorangestellten als auch die nicht vorangestellten Elemente die gleiche Namespace-URL, daher sollten Sie überhaupt kein Problem haben.

Java 8-Bibliothek Dynamics ignoriert den Namespace standardmäßig (kann aber explizit sein, wenn gewünscht, dh in den seltenen Fällen, wenn es wirklich darauf ankommt). Die Bibliothek ist keine Abfragesprache, sondern eine ziemlich direkte Art, mit dynamischen Strukturen umzugehen. Als solche Rekursion ist einfach, so können wir alle Elemente so scannen:

{ 
    XmlDynamic example = new XmlDynamic(xmlStringOrReaderOrInputSourceEtc); 

    List<String> ids = allElements(example) 
     .filter(hasElementName("fptr")) // import static alexh.weak.XmlDynamic.hasElementName; 
     .map(fptr -> fptr.get("@ID").asString()) 
     .collect(toList()); 
    // [DTL21, DTL22, DTL11] 
} 

/** recursively stream all elements */ 
Stream<Dynamic> allElements(Dynamic root) { 
    return Stream.concat(Stream.of(root), root.children().flatMap(child -> allElements(child))); 
} 
+0

Klingt interessant. Hast du diese Lib geschrieben? – jackthehipster

+0

@jackthehipster Ja. Es ist eigentlich eine allgemeine Bibliothek für die Arbeit mit verschachtelten, schwach typisierten Daten, XmlDynamic ist eine spezialisierte Implementierung für XML. Github finden Sie unter https://github.com/alexheretic/dynamics#xml-dynamics –

Verwandte Themen