Ich muss ein XML-Dokument analysieren, das so aussieht:
<?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" manchmal unterschiedlich sein kann. Ich möchte es komplett ignorieren und meine Daten einfach vom Tag MessagePayload Downstream beziehen.
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 sich der Namespace nie ändert, aber das ist offensichtlich nicht der Fall. Was muss ich tun, damit der Namespace ignoriert wird? Oder wie kann ich alle möglichen Namespace-Werte an die XPath-Instanz übergeben, wenn ich sie kenne?
Verwenden:
/*/*/*/*/*
[local-name()='REPORT_DATA'
or
local-name()='REPORT_HEADER'
]
Möchte jemand eine umfassendere Syntax?
String xPathExpression = "/*[local-name()='OASISReport]
/*[local-name()='MessagePayload]
/*[local-name()='RTO]
/*[local-name()='REPORT_ITEM]
/*[local-name()='REPORT_DATA"];
Übrigens, wenn der XPath auch die Elementindexposition benötigt:
String xPathExpression = "/*[local-name()='OASISReport][1]
Dies ist FAQ (aber ich bin faul, Duplikate heute zu suchen)
In XPath 1.0
//*[local-name()='name']
Wählt jedes Element mit "name" als lokaler Name aus.
In XPath 2.0 können Sie Folgendes verwenden:
//*:name