如何使用XdmNode从标签读取命名空间?

时间:2017-05-18 06:47:48

标签: java xml parsing namespaces saxon

我希望从net.sf.saxon.s9api.XdmNode中的一个标签中读取所有名称空间。我可以使用下面的代码读取它们,但由于性能问题,我应该使用现有的DOM来解析和读取命名空间。

  

input.xml中

<?xml version="1.0" encoding="utf-8"?>
<?taxonomy-version 2.2.3.0?> <?taxonomy-set-overall-version 2.6.0.0?>
<!--(C) EBA-->
<link:linkbase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:link="http://www.xbrl.org/2003/linkbase" xmlns:gen="http://xbrl.org/2008/generic" xmlns:label="http://xbrl.org/2008/label" xmlns:formula="http://xbrl.org/2008/formula" xmlns:df="http://xbrl.org/2008/filter/dimension" xmlns:table="http://xbrl.org/2014/table" xmlns:model="http://www.eurofiling.info/xbrl/ext/model" xmlns:eba_dim="http://www.eba.europa.eu/xbrl/crr/dict/dim" xmlns:eba_PL="http://www.eba.europa.eu/xbrl/crr/dict/dom/PL" xmlns:eba_met="http://www.eba.europa.eu/xbrl/crr/dict/met" xmlns:eba_BA="http://www.eba.europa.eu/xbrl/crr/dict/dom/BA" xmlns:eba_MC="http://www.eba.europa.eu/xbrl/crr/dict/dom/MC" xmlns:eba_IM="http://www.eba.europa.eu/xbrl/crr/dict/dom/IM" xmlns:eba_AP="http://www.eba.europa.eu/xbrl/crr/dict/dom/AP" xmlns:eba_TR="http://www.eba.europa.eu/xbrl/crr/dict/dom/TR" xmlns:eba_EC="http://www.eba.europa.eu/xbrl/crr/dict/dom/EC" xmlns:eba_CT="http://www.eba.europa.eu/xbrl/crr/dict/dom/CT" xmlns:eba_GA="http://www.eba.europa.eu/xbrl/crr/dict/dom/GA" xsi:schemaLocation="http://www.xbrl.org/2003/linkbase http://www.xbrl.org/2003/xbrl-linkbase-2003-12-31.xsd http://xbrl.org/2008/generic http://www.xbrl.org/2008/generic-link.xsd http://xbrl.org/2008/label http://www.xbrl.org/2008/generic-label.xsd http://xbrl.org/2008/formula http://www.xbrl.org/2008/formula.xsd http://xbrl.org/2008/filter/dimension http://www.xbrl.org/2008/dimension-filter.xsd http://xbrl.org/2014/table http://www.xbrl.org/2014/table.xsd http://www.eurofiling.info/xbrl/ext/model http://www.eurofiling.info/eu/fr/xbrl/ext/model.xsd">
<link:arcroleRef arcroleURI="http://xbrl.org/arcrole/2014/aspect-node-filter" xlink:type="simple" xlink:href="http://www.xbrl.org/2014/table.xsd#aspect-node-filter" />
<link:arcroleRef arcroleURI="http://xbrl.org/arcrole/2014/breakdown-tree" xlink:type="simple" xlink:href="http://www.xbrl.org/2014/table.xsd#breakdown-tree" />
<link:arcroleRef arcroleURI="http://xbrl.org/arcrole/2014/definition-node-subtree" xlink:type="simple" xlink:href="http://www.xbrl.org/2014/table.xsd#definition-node-subtree" />
<link:arcroleRef arcroleURI="http://xbrl.org/arcrole/2014/table-breakdown" xlink:type="simple" xlink:href="http://www.xbrl.org/2014/table.xsd#table-breakdown" />
<link:roleRef roleURI="http://www.eba.europa.eu/xbrl/crr/role/dict/dom/GA/GA5_1" xlink:type="simple" xlink:href="../../../../../../dict/dom/ga/hier.xsd#eba_GA5_1" />
<link:roleRef roleURI="http://www.eba.europa.eu/xbrl/crr/role/fws/COREP/its-2016-03/2016-11-15/tab/C_09.01.a" xlink:type="simple" xlink:href="c_09.01.a.xsd#role" />
</link:linkbase>

从上面的文件中,我希望从link:linkbase标签中读取所有“xmlns”属性。

以下代码段按预期工作但达到了性能。

  

代码

private List<Namespace> getNameSpaceListFromFile() throws ValidationException {
    List <Namespace>nsList = new ArrayList<Namespace>();

    try {
        if(inputFile!=null){
            BufferedReader bufferedReader = new BufferedReader(new FileReader(inputFile)); //I18NOK:IOE
            String line;
            StringBuilder stringBuilder = new StringBuilder();

            while((line=bufferedReader.readLine())!= null){
                stringBuilder.append(line.trim());
            }
            XMLStreamReader reader =  XMLInputFactory.newFactory().createXMLStreamReader(new StringReader(stringBuilder.toString().trim().replaceFirst("^([\\W]+)<","<"))); /*I18NOK:LSM*/ //removing byte order markers by using "^([\\W]+)<","<" 

            while (reader.hasNext()) {
                int event = reader.next();
                if (XMLStreamConstants.START_ELEMENT == event) {
                    if (reader.getNamespaceCount() > 0) {
                        for (int nsIndex = 0; nsIndex < reader.getNamespaceCount(); nsIndex++) {
                            System.out.println(reader.getNamespacePrefix(nsIndex).trim()+"\t\t:\t\t"+ reader.getNamespaceURI(nsIndex).trim());
                            nsList.add(new Namespace(reader.getNamespacePrefix(nsIndex).trim(), reader.getNamespaceURI(nsIndex).trim()));
                        }
                    }
                } 
            }
            bufferedReader.close();
        }
        if(nsList.isEmpty()){
            return new NamespaceLoader(context).getNsListFromProperties();
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
    return nsList;
}

我搜索了正确的工作解决方案,但找不到任何。

Iterator <XdmItem> itemList  = document.axisIterator(Axis.CHILD);
        while(itemList.hasNext()) {
            XdmItem item = itemList.next();
            System.err.println(item.getStringValue());
        }

在上面的代码中,我在XdmItem中获得了完整的“link”标记,但是找不到一种方法来读取linkbase标记并获取命名空间。

任何形式的帮助将不胜感激。另外,如果需要更多信息,请告诉我。

1 个答案:

答案 0 :(得分:1)

如果我理解正确,您已将该文档作为XdmNode的实例保存。如果是这种情况,那么您可以使用s9api接口来执行XPath表达式

/*/namespace(*)

这将返回一个XdmValue,其中包含最外层元素上的命名空间节点列表。然后你可以做

for (XdmItem item : result) {
   XdmNode ns = (XdmNode)item;
   String prefix = ns.getNodeName()==null ? "" : ns.getNodeName().getLocalName();
   String uri = ns.getStringValue();
   ...
}

如果您愿意,可以通过在文档节点上使用XdmNode.axisIterator(Axis.CHILD)来查找最外层元素,然后XdmNode.axisIterator(Axis.NAMESPACE)来查找命名空间节点,从而达到相同的效果。