首页 \ 问答 \ Xpath - Java - 从XML中提取多个名称空间(Xpath - Java - Extracting multiple namespaces from XML)

Xpath - Java - 从XML中提取多个名称空间(Xpath - Java - Extracting multiple namespaces from XML)

我正在研究用Java编写的解析器。 我可以从各个位置接收带有各种内容的XML提要。 我需要从feed中提取所有名称空间,根据feed调用this或that。 我在使用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"

因此,不会返回“demons”命名空间。 问题是,如果我在一个节点上放置几个名称空间,则在Java中只返回1,而在XSL脚本上则显示所有名称空间。

我希望我能清楚自己。 我花了几天时间在网页上浏览一些例子,我不知道我是否真的很接近,但只是遗漏了一些东西,或者我的表情根本不合适......

提前致谢。

好的,所以我最终使用xPath 2.0来完成它,使用saxon-HE 9.4:

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

    }  

I am working on a parser written in Java. I can receive XML feeds from various locations, with various contents. I need to extract all the namespaces from the feed, to call this or that according to the feed. I have some trouble obtaining this in Java, and i am not really sure where the issue is.

Let's consider this 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>

In order to test my xPath expression (i am rather new to it), i wrote a little .xsl script applied to that 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::*">
            <xsl:value-of select="." />
            <xsl:text> </xsl:text><br />
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

And this correctly provides me the list of namespaces encountered iterating the nodes:

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 

Now i get back to Java: here is the code i use.

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

And here is the result i obtain:

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

Therefore, the "demons" namespace is not returned. The problem is that if i put several namespaces on 1 node, only 1 is return in Java, whereas on the XSL script all are displayed.

I hope i maed myself clear; i spent the past days on the web browsing for examples, and i dont know if im really close but just missing a little something or if my expression is simply not proper..

Thanks in advance.

OK so i eventually used xPath 2.0 to do it, using saxon-HE 9.4:

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

    }  

原文:https://stackoverflow.com/questions/21157255
更新时间:2023-05-06 19:05

相关问答

更多

相关文章

更多

最新问答

更多
  • 获取MVC 4使用的DisplayMode后缀(Get the DisplayMode Suffix being used by MVC 4)
  • 如何通过引用返回对象?(How is returning an object by reference possible?)
  • 矩阵如何存储在内存中?(How are matrices stored in memory?)
  • 每个请求的Java新会话?(Java New Session For Each Request?)
  • css:浮动div中重叠的标题h1(css: overlapping headlines h1 in floated divs)
  • 无论图像如何,Caffe预测同一类(Caffe predicts same class regardless of image)
  • xcode语法颜色编码解释?(xcode syntax color coding explained?)
  • 在Access 2010 Runtime中使用Office 2000校对工具(Use Office 2000 proofing tools in Access 2010 Runtime)
  • 从单独的Web主机将图像传输到服务器上(Getting images onto server from separate web host)
  • 从旧版本复制文件并保留它们(旧/新版本)(Copy a file from old revision and keep both of them (old / new revision))
  • 西安哪有PLC可控制编程的培训
  • 在Entity Framework中选择基类(Select base class in Entity Framework)
  • 在Android中出现错误“数据集和渲染器应该不为null,并且应该具有相同数量的系列”(Error “Dataset and renderer should be not null and should have the same number of series” in Android)
  • 电脑二级VF有什么用
  • Datamapper Ruby如何添加Hook方法(Datamapper Ruby How to add Hook Method)
  • 金华英语角.
  • 手机软件如何制作
  • 用于Android webview中图像保存的上下文菜单(Context Menu for Image Saving in an Android webview)
  • 注意:未定义的偏移量:PHP(Notice: Undefined offset: PHP)
  • 如何读R中的大数据集[复制](How to read large dataset in R [duplicate])
  • Unity 5 Heighmap与地形宽度/地形长度的分辨率关系?(Unity 5 Heighmap Resolution relationship to terrain width / terrain length?)
  • 如何通知PipedOutputStream线程写入最后一个字节的PipedInputStream线程?(How to notify PipedInputStream thread that PipedOutputStream thread has written last byte?)
  • python的访问器方法有哪些
  • DeviceNetworkInformation:哪个是哪个?(DeviceNetworkInformation: Which is which?)
  • 在Ruby中对组合进行排序(Sorting a combination in Ruby)
  • 网站开发的流程?
  • 使用Zend Framework 2中的JOIN sql检索数据(Retrieve data using JOIN sql in Zend Framework 2)
  • 条带格式类型格式模式编号无法正常工作(Stripes format type format pattern number not working properly)
  • 透明度错误IE11(Transparency bug IE11)
  • linux的基本操作命令。。。