繁体   English   中英

Xpath-Java-从XML提取多个名称空间

[英]Xpath - Java - Extracting multiple namespaces from XML

我正在研究用Java编写的解析器。 我可以从不同位置接收具有各种内容的XML feed。 我需要从提要中提取所有名称空间,以根据提要来调用此名称空间。 我在用Java获取此代码时遇到了一些麻烦,而且我不太确定问题出在哪里。

让我们考虑以下XML:

<?xml version="1.0"?>
        <?xml-stylesheet type='text/xsl' href='new.xsl'?>
<test xmlns:mynsone="http://www.ns.com/test" xmlns:demons="http://www.demons.com/test">
    <p xmlns:domain="http://www.toto.com/test">
        this is a test.
    </p>
</test>

为了测试我的xPath表达式(我还很陌生),我编写了一个应用于该XML的.xsl脚本:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output
            method="html"
            encoding="ISO-8859-1"
            doctype-public="-//W3C//DTD XHTML//EN"
            doctype-system="http://www.w3.org/TR/2001/REC-xhtml11-20010531"
            indent="yes" />
    <xsl:template match="/">
        <xsl:for-each select="//namespace::*">
            <xsl:value-of select="." />
            <xsl:text> </xsl:text><br />
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

这正确地为我提供了迭代节点时遇到的名称空间列表:

http://www.w3.org/XML/1998/namespace 
http://www.demons.com/test 
http://www.ns.com/test 
http://www.w3.org/XML/1998/namespace 
http://www.demons.com/test 
http://www.ns.com/test 
http://www.toto.com/test 

现在我回到Java:这是我使用的代码。

    InputStream file = url.openStream();
    DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder =  builderFactory.newDocumentBuilder();
    org.w3c.dom.Document xmlDocument = builder.parse(file);

    XPath xPath = XPathFactory.newInstance().newXPath();
    String expression = "//namespace::*";
    System.out.println(expression);

    NodeList nodelist = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);

    for (int k = 0; k < nodelist.getLength(); k++)
    {
        Node mynode = nodelist.item(k);
        System.out.println(mynode.toString());
    }  

这是我获得的结果:

xmlns:mynsone="http://www.ns.com/test"
org.apache.xml.dtm.ref.dom2dtm.DOM2DTMdefaultNamespaceDeclarationNode@7dbb8ca4
xmlns:domain="http://www.toto.com/test"

因此,不返回“守护程序”名称空间。 问题是,如果我在1个节点上放置几个名称空间,则Java中仅返回1个名称空间,而在XSL脚本上则全部显示。

希望我能使自己清楚。 我花了过去的时间在网络上浏览示例,我不知道即时消息真的关闭了,但是只是缺少了一些东西还是我的表达方式不合适。

提前致谢。

好的,所以我最终使用saxon-HE 9.4使用xPath 2.0来做到这一点:

public static boolean detectGeoRssNamespace(InputStream sourceFeed) {
    try {
        if (sourceFeed.markSupported()) {
            sourceFeed.reset();
        }

        String objectModel = NamespaceConstant.OBJECT_MODEL_SAXON;
        System.setProperty("javax.xml.xpath.XPathFactory:"+NamespaceConstant.OBJECT_MODEL_SAXON, "net.sf.saxon.xpath.XPathFactoryImpl");
        XPathFactory xpathFactory = XPathFactory.newInstance(objectModel);
        XPath xpath = xpathFactory.newXPath();

        InputSource is = new InputSource(sourceFeed);
        SAXSource ss = new SAXSource(is);
        NodeInfo doc = ((XPathEvaluator)xpath).setSource(ss);       

        String xpathExpressionStr = "distinct-values(//*[name()!=local-name()]/ concat('prefix=', substring-before(name(), ':'), '&uri=', namespace-uri()))";
        XPathExpression xpathExpression = xpath.compile(xpathExpressionStr);

        List nodelist = (List)xpathExpression.evaluate(doc, XPathConstants.NODESET);

         System.out.println("<output>");
         Iterator iter = nodelist.iterator();
         while ( iter.hasNext() ) {
             Object line = (Object)iter.next();
             System.out.println(line.toString());
         }
         System.out.println("</output>");

    } catch (XPathFactoryConfigurationException e) {
        e.printStackTrace();
    } catch (XPathException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();                

    }  

如果将此名称空间提取到不同的xml元素该怎么办。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output
            method="html"
            encoding="ISO-8859-1"
            doctype-public="-//W3C//DTD XHTML//EN"
            doctype-system="http://www.w3.org/TR/2001/REC-xhtml11-20010531"
            indent="yes" />
    <xsl:template match="/">
        <xsl:for-each select="//namespace::*">
          <namespace>
            <xsl:value-of select="." />
          </namespace>
            <xsl:text> </xsl:text><br />
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

使用xPath 2.0(问题中包含的代码)解决了问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM