2010-12-09 4 views
48

Je dois analyser un document XML qui ressemble à ceci:Comment ignorer l'espace de noms lors de la sélection des noeuds XML avec XPath

<?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> 

Le problème est que l'espace de noms « http://oasissta.caiso.com/mrtu -oasis/xsd/OASISReport.xsd "peut parfois être différent. Je veux l'ignorer complètement et juste obtenir mes données de l'étiquette MessagePayload en aval.

Le code J'utilise à ce jour est:

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()); 

Il fonctionne très bien si l'espace de noms ne change jamais, mais qui est évidemment pas le cas. Que dois-je faire pour l'ignorer? Ou si je connais l'ensemble de toutes les valeurs d'espace de noms possibles, comment puis-je les transmettre à l'instance XPath?

+2

@ user452103: XPath est les noms XML se plaignent, donc il ne sera jamais ignorer l'espace de noms. Vous pouvez utiliser ** expression ** qui sélectionne les noeuds relatifs à l'espace de noms. Si l'URI de l'espace de noms change si souvent, alors l'URI est incorrect. ** L'URI de l'espace de noms suppose que cet élément appartient à un vocabulaire XML spécifique **. –

+0

@ user452103: Gardez cette mise en forme, c'est plus clair. –

+1

@Alejandro: merci pour le formatage, ça a l'air mieux maintenant. Quelle expression puis-je utiliser pour sélectionner des noeuds sans tenir compte de l'espace de noms? – lukegf

Répondre

35

Utilisation:

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

voulez-vous dire utiliser la valeur de xPathExpression dans le code ci-dessus? – lukegf

+0

@ user452103: Oui, exactement. C'est l'expression XPath à utiliser. –

+0

donc, juste pour clarifier, devrait-il être comme ceci maintenant: String xPathExpression = "/ */*/*/*/* [nom-local() = 'REPORT_DATA' ou nom-local() = 'REPORT_HEADER']" ; – lukegf

104

C'est FAQ (mais je suis paresseux pour rechercher les doublons aujourd'hui)

Dans XPath 1,0

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

Sélectionne tout élément avec "nom" comme -nom local.

Dans XPath 2.0, vous pouvez utiliser:

//*:name 
Questions connexes