2010-12-09 5 views
48

Ich habe ein XML-Dokument zu analysieren, die wie folgt aussieht:Wie Namensraum zu ignorieren, wenn XML-Knoten mit XPath Auswahl

<?xml version="1.0" encoding="UTF-8" ?> 
<m:OASISReport xmlns:m="http://oasissta.caiso.com/mrtu-oasis/xsd/OASISReport.xsd" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xsi:schemaLocation="http://oasissta.caiso.com/mrtu-oasis/xsd/OASISReport.xsd http://oasissta.caiso.com/mrtu-oasis/xsd/OASISReport.xsd"> 
    <m:MessagePayload> 
    <m:RTO> 
    <m:name>CAISO</m:name> 
    <m:REPORT_ITEM> 
    <m:REPORT_HEADER> 
     <m:SYSTEM>OASIS</m:SYSTEM> 
     <m:TZ>PPT</m:TZ> 
     <m:REPORT>AS_RESULTS</m:REPORT> 
     <m:MKT_TYPE>HASP</m:MKT_TYPE> 
     <m:UOM>MW</m:UOM> 
     <m:INTERVAL>ENDING</m:INTERVAL> 
     <m:SEC_PER_INTERVAL>3600</m:SEC_PER_INTERVAL> 
    </m:REPORT_HEADER> 
    <m:REPORT_DATA> 
     <m:DATA_ITEM>NS_PROC_MW</m:DATA_ITEM> 
     <m:RESOURCE_NAME>AS_SP26_EXP</m:RESOURCE_NAME> 
     <m:OPR_DATE>2010-11-17</m:OPR_DATE> 
     <m:INTERVAL_NUM>1</m:INTERVAL_NUM> 
     <m:VALUE>0</m:VALUE> 
    </m:REPORT_DATA> 

Das Problem ist, dass der Namespace „http://oasissta.caiso.com/mrtu -oasis/xsd/OASISReport.xsd "kann manchmal anders sein. Ich möchte es vollständig ignorieren und meine Daten nur vom Tag MessagePayload downstream erhalten.

Der Code, den ich bisher benutze ist:

String[] namespaces = new String[1]; 
    String[] namespaceAliases = new String[1]; 

    namespaceAliases[0] = "ns0"; 
    namespaces[0] = "http://oasissta.caiso.com/mrtu-oasis/xsd/OASISReport.xsd"; 

    File inputFile = new File(inputFileName); 

    Map namespaceURIs = new HashMap(); 

    // This query will return all of the ASR records. 
    String xPathExpression = "/ns0:OASISReport 
          /ns0:MessagePayload 
           /ns0:RTO 
           /ns0:REPORT_ITEM 
           /ns0:REPORT_DATA"; 
    xPathExpression += "|/ns0:OASISReport 
         /ns0:MessagePayload 
         /ns0:RTO 
          /ns0:REPORT_ITEM 
          /ns0:REPORT_HEADER"; 

    // Load up the raw XML file. The parameters ignore whitespace and other 
    // nonsense, 
    // reduces DOM tree size. 
    SAXReader reader = new SAXReader(); 
    reader.setStripWhitespaceText(true); 
    reader.setMergeAdjacentText(true); 
    Document inputDocument = reader.read(inputFile); 

    // Relate the aliases with the namespaces 
    if (namespaceAliases != null && namespaces != null) 
    { 
    for (int i = 0; i < namespaceAliases.length; i++) 
    { 
    namespaceURIs.put(namespaceAliases[i], namespaces[i]); 
    } 
    } 

    // Cache the expression using the supplied namespaces. 
    XPath xPath = DocumentHelper.createXPath(xPathExpression); 
    xPath.setNamespaceURIs(namespaceURIs); 

    List asResultsNodes = xPath.selectNodes(inputDocument.getRootElement()); 

Es funktioniert gut, wenn der Namespace nie aber das ändert, ist offensichtlich nicht der Fall. Was muss ich tun, damit der Namespace ignoriert wird? Oder wenn ich die Menge aller möglichen Namespace-Werte kenne, wie kann ich sie alle an die XPath-Instanz übergeben?

+2

@ user452103: XPath ist XML Namen beschweren, so wird es nie Namespace ignorieren. Sie können ** Ausdruck ** verwenden, der Knoten in Bezug auf den Namespace auswählt. Wenn sich der Namespace-URI so häufig ändert, ist der falsche URI vorhanden. ** Namespace-URI soll angeben, dass das Element zu einem bestimmten XML-Vokabular ** gehört. –

+0

@ user452103: Behalten Sie diese Formatierung, es ist klarer. –

+1

@Alejandro: danke für die Formatierung, es sieht jetzt besser aus. Mit welchem ​​Ausdruck kann ich Knoten unabhängig vom Namespace auswählen? – lukegf

Antwort

35

Verwendung:

/*/*/*/*/* 
     [local-name()='REPORT_DATA' 
     or 
     local-name()='REPORT_HEADER' 
     ] 
+0

meinst du das als Wert von xPathExpression im obigen Code zu verwenden? – lukegf

+0

@ user452103: Ja genau. Dies ist der zu verwendende XPath-Ausdruck. –

+0

Also, nur um zu klären, sollte es jetzt so sein: String xPathExpression = "/ */*/*/*/* [local-name() = 'REPORT_DATA' oder local-name() = 'REPORT_HEADER']" ; – lukegf

104

Dies ist FAQ (aber ich bin faul Duplikate heute suchen) mit "Name" als local-name

In XPath 1,0

//*[local-name()='name'] 

Wählt ein beliebiges Element.

In XPath 2.0 können Sie verwenden:

//*:name