【问题标题】:How to ignore namespace when selecting XML nodes with XPath使用 XPath 选择 XML 节点时如何忽略命名空间
【发布时间】:2011-05-23 02:03:09
【问题描述】:

我必须解析一个如下所示的 XML 文档:

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

问题在于命名空间“http://oasissta.caiso.com/mrtu-oasis/xsd/OASISReport.xsd”有时可能不同。我想完全忽略它,只从下游标签 MessagePayload 获取我的数据。

目前我使用的代码是:

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

如果命名空间从不改变,它工作正常,但显然情况并非如此。我需要做什么才能让它忽略命名空间?或者,如果我知道所有可能的命名空间值的集合,我如何将它们全部传递给 XPath 实例?

【问题讨论】:

  • @user452103:XPath 是 XML 名称的抱怨,所以它永远不会忽略命名空间。您可以使用 expression 来选择有关命名空间的节点。如果命名空间 URI 经常更改,那么就是错误的 URI。 命名空间 URI 假设表明该元素属于特定的 XML 词汇表
  • @user452103:保持这种格式,更清晰。
  • @Alejandro:感谢您的格式化,现在看起来好多了。无论命名空间如何,我可以使用什么表达式来选择节点?
  • 好问题,+1。请参阅我对一个 XPath 1.0 表达式的回答,该表达式准确地选择了想要的节点。 :)

标签: xml xpath namespaces xml-namespaces


【解决方案1】:

这是常见问题解答(但我今天懒得搜索重复项)

在 XPath 1.0 中

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

选择任何带有“名称”作为local-name的元素。

在 XPath 2.0 中,您可以使用:

//*:name

【讨论】:

    【解决方案2】:

    使用

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

    【讨论】:

    • 你的意思是在上面的代码中使用它作为 xPathExpression 的值吗?
    • @user452103:是的,没错。这是要使用的 XPath 表达式。
    • 所以,澄清一下,现在应该是这样的: String xPathExpression = "/*/*/*/*/*[local-name()='REPORT_DATA' 或 local-name( )='REPORT_HEADER']";
    • @user452103:是的,你为什么不试试呢?此表达式在提供的 XML 文档中选择两个想要的节点。
    • @ClaraOnager,这会选择顶部以下第 4 层的任何元素,其 local-name() 是“REPORT_DATA”或“REPORT_HEADER”
    猜你喜欢
    • 2011-05-25
    • 1970-01-01
    • 2013-11-29
    • 1970-01-01
    • 2010-10-06
    • 2011-12-05
    • 2015-02-18
    • 2012-11-10
    • 1970-01-01
    相关资源
    最近更新 更多