2016-04-10 4 views
1

ich eine XML-Datei habe, unten erwähnt:Java: Parsen von XML-Datei mit SAX/XPATH

<?xml version="1.0" encoding="UTF-8"?> 
<Workbook> 
    <ExcelWorkbook 
    xmlns="urn:schemas-microsoft-com:office:excel"/> 
     <Worksheet ss:Name="Table 1"> 
      <Table> 
       <Row ss:Index="7" ss:AutoFitHeight="0" ss:Height="12"> 
       <Cell ss:Index="1" ss:StyleID="s05"> 
        <ss:Data ss:Type="String" 
         xmlns="http://www.w3.org/TR/REC-html40"> 
         <Font html:Size="9" html:Face="Times New Roman" x:Family="Roman" html:Color="#000000"> 
         ABCD 
         </Font> 
        </ss:Data> 
       </Cell> 
      </Row> 

Wie extrahieren wir die Daten "ABCD" hier, SAX oder XPath in Java verwenden?

EDIT 1:

Dies ist die XML-

<Table> 
<Row ss:Index="74" ss:AutoFitHeight="0" ss:Height="14"> 
    <Cell ss:Index="1" ss:MergeAcross="3" ss:StyleID="s29"> 
     <ss:Data ss:Type="Number" xmlns="http://www.w3.org/TR/REC-html40"> 
     0.00 
     </ss:Data> 
    </Cell> 
    <Cell ss:Index="15" ss:MergeAcross="5" ss:StyleID="s29"> 
     <ss:Data ss:Type="Number" xmlns="http://www.w3.org/TR/REC-html40"> 
     4.57 
     </ss:Data> 
    </Cell> 
</Row> 
+1

Muss es SAX sein? XPATH ist viel besser geeignet für die Suche in XML doc –

+0

@sharonbn XPATH wäre in Ordnung, aber ich bin überhaupt nicht damit vertraut. Kannst du mir bitte helfen? – Dax

+0

@sharonbn Ich habe Ihren Code geändert. 'String cellStringContent ="/* [@ ss: Typ = 'Nummer']/* [Text()]/text() ";'. Aber es gibt einen Fehler hier- 'if (n.getNodeType() == Node.TEXT_NODE)'. Anstelle von TEXT_NODE habe ich versucht, andere nodeType benannte Konstanten zu verwenden, aber es hat nicht funktioniert. Bitte helfen Sie. – Dax

Antwort

1

Die Lösung geht davon aus, dass die Frage, wie Sie den Text für jede Zelle auf Zeilen- und Spaltennummern basiert erhalten.

Es hat eine Weile gedauert, bis ich die Lösung gefunden habe, weil Namespaces im Eingabedokument verwendet wurden. Offenbar kann Xpath keine qualifizierten Elemente und Attribute ohne einen Namespaceprozessor und ein HSA analysieren, um eine Schnittstelle für diesen Zweck zu implementieren (es gibt keinen Standard?), also fand ich eine map-basierte Implementierung here und verwendete sie.

Angenommen, Sie haben die Klasse von der Verknüpfung in Ihrer Quellstruktur, der folgende Code funktioniert. Ich brach das Suchmuster auf mehrere Variablen aus Gründen der Klarheit

public static String getCellValue(String filename, int rowIdx, int colIdx) { 
    // search for Table element anywhere in the source 
    String tableElementPattern = "//*[name()='Table']"; 
    // search for Row element with given number 
    String rowPattern = String.format("/*[name()='Row' and @ss:Index='%d']", rowIdx) ; 
    // search for Cell element with given column number 
    String cellPattern = String.format("/*[name()='Cell' and @ss:Index='%d']", colIdx) ; 
    // search for element that has ss:Type="String" attribute, search for element with text under it and get text name 
    String cellStringContent = "/*[@ss:Type='String']/*[text()]/text()"; 
    String completePattern = tableElementPattern + rowPattern + cellPattern + cellStringContent; 

    try (FileReader reader = new FileReader(filename)) { 
     XPath xPath = getXpathProcessor(); 
     Node n = (Node)xPath.compile(completePattern) 
     .evaluate(new InputSource(reader), XPathConstants.NODE); 
     if (n.getNodeType() == Node.TEXT_NODE) { 
      return n.getNodeValue().trim(); 
     } 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    return null; 
} 

private static XPath getXpathProcessor() { 
    // this is where the custom implementation of NamespaceContext is used 
    NamespaceContext context = new NamespaceContextMap(
     "html", "http://www.w3.org/TR/REC-html40", 
     "xsl", "http://www.w3.org/1999/XSL/Transform", 
     "o", "urn:schemas-microsoft-com:office:office", 
     "x", "urn:schemas-microsoft-com:office:excel", 
     "ss", "urn:schemas-microsoft-com:office:spreadsheet"); 
    XPath xpath = XPathFactory.newInstance().newXPath(); 
    xpath.setNamespaceContext(context); 
    return xpath; 
} 

Aufruf:

System.out.println(getCellValue("C://Temp/xx.xml", 7, 1)); 

erzeugt die gewünschte Ausgabe

+0

Es funktionierte. Danke vielmals! – Dax

0

Unten ist der Code Ihre XML mit vtd-xml zu tun abfragen .. .

import com.ximpleware.*; 

public class queryXML{ 

public static void main(String[] s) throws VTDException{ 

     VTDGen vg = new VTDGen(); 
     vg.selectLcDepth(5); 
     if (!vg.parseFile("d:\\xml\\test11.xml", false)) 
      return; 
     VTDNav vn = vg.getNav(); 
     AutoPilot ap = new AutoPilot(vn); 
     ap.declareNameSpace("ss","urn:schemas-microsoft-com:office:spreadsheet"); 
       ap.selectXPath("/Workbook/ExcelWorkbook/Worksheet/Table/Cell/ss:data/font/text()"); 
int i=0; 
while((i=ap.evalXPath())!=-1){ 
System.out.println(" data content ==>"+vn.toString(i); 
} 


} 


}