Java XPath

http://www.ibm.com/developerworks/cn/xml/x-javaxpathapi.html

 

http://blog.youkuaiyun.com/PigHeadSam/archive/2008/10/29/3173907.aspx

 

http://liugang594.javaeye.com/blog/260522

 

声明:以下的测试是用的jdk1.4.2,xalan7.0对于如下xml文档片断:

<ML:MREML xmlns:ML="MREML">
    <EnvelopEntity>
        <EnvelopID>GUID2006102000002</EnvelopID>
        <EnvelopVersion>1.0.1R</EnvelopVersion>
        <ExchangeTime>2006-10-25 13:12:10</ExchangeTime>
        <SendFrom>
            <SFID>SOBEY_NEWS</SFID>
                           <SFDescription>SOBEY新闻系统</SFDescription>
        </SendFrom>
        <SendTo>
            <STID>DAYANG_MAM</STID>
            <STDescription>DAYANG媒资系统</STDescription>
        </SendTo>
        <Priority>2</Priority>
        <EntityInfo>
            <EntityID>REQUEST_ID_01</EntityID>
            <EntityType>4</EntityType>
        </EntityInfo>
        <EntityInfo>
            <EntityID>节目GUID</EntityID>
            <EntityType>3</EntityType>
        </EntityInfo>
        <EntityInfo>
            <EntityID>管理信息实体ID</EntityID>
            <EntityType>2</EntityType>
        </EntityInfo>
    </EnvelopEntity>
</ML:MREML >
    对于上述含有命名空间的xml文档,如果想通过xpath查找EnvelopID的值,有两种方式:1.通过利用xpath的函数local-name()

    如上述查找内容的xpath表达式可以写为://*[local-name()='MREML']/EnvelopEntity/EnvelopID/text()

    2.通过在java程序中处理上述文档的命名空间是定义的,如果要使xpath表达式能正确地被解析需要在java程序中建立起prefix和uri二者的映射关系
    public static Node parseXPath(String expression, Object obj, QName qname)
            throws Exception {
        javax.xml.xpath.XPath xpath = javax.xml.xpath.XPathFactory.newInstance().newXPath();
        xpath.setNamespaceContext(getNamespaceContext());
        if (qname.equals(XPathConstants.NODE))
            return (Node) xpath.evaluate(expression, obj, qname);
        return null;
    }

  public static NamespaceContext getNamespaceContext() throws Exception {
        return new NamespaceContext() {
            public String getNamespaceURI(String prefix) {
/*
                // 一种方式:
                //这里可以采用配置文件的方式,先将所需要使用的xmlNamespace配置好,
                //采用注册的方式供应用使用,这种方式效率应该高一些,不用每次都要从文档中提取namespace
                //不过没有第二种方便
                String uri;
                if (prefix.equalsIgnoreCase("ML"))
                    uri = "MREML";
                else if (prefix.equalsIgnoreCase("RE"))
                    uri = "http://herry.com.cn";
                else if (prefix.equalsIgnoreCase("RID"))
                    uri = "ResourceID";
                else if (prefix.equalsIgnoreCase("RUI"))
                    uri = "ResourceUniqueID";
                else if (prefix.equalsIgnoreCase("RMDI"))
                    uri = "ResourceMetaDataInfo";
                else
                    uri = null;
                System.out.println(ParseXMLUtil.class + "::getNamespaceURI:prefix= " + prefix);
                return uri;
*/
                /*
                                //                另外一种方式: 通过PrefixResolver来提取出prefix和Namespace的对应关系
                                                final PrefixResolver resolver =
                                                        new PrefixResolverDefault(doc.getDocumentElement());

                                                return resolver.getNamespaceForPrefix(prefix);

                */
                
            // Dummy implementation - not used!
            public java.util.Iterator getPrefixes(String val) {
                return null;
            }

            // Dummy implemenation - not used!
            public String getPrefix(String uri) {
                return null;
            }
        };
    }
    若要查找ResourceUniqueID的值,则xpath应该书写为://ML:MREML/ML:ResourceEntity/RMDI:ResourceMetaDataInfo/RMDI:ResourceID/RUI:ResourceUniqueID/text()

    这里的ML(prefix)和URI(MERML)等已经通过

    对于含有默认命名空间地文档如果采用NamespaceContext的方式,即将prefix和uri已经映射起来,如对于以下的文档:
<MREML xmlns="MREML"><ResourceEntity >
        <ResourceMetaDataInfo>
            <ResourceID xmlns="ResourceID">
                <RUI:ResourceUniqueID xmlns:RUI="ResourceUniqueID">节目GUID</RUI:ResourceUniqueID>
                <UserDefID>UserDefID填写节目代码</UserDefID>
            </ResourceID>
            <Title>
                <ResourceName>911新闻素材</ResourceName>
            </Title>
            <ResourceType>1</ResourceType>
            <Subject>
                <KeyWords>911 袭击</KeyWords>
            </Subject>
            <Description>
                <ContentDescription>美国遭遇911袭击现场30S画面及同期声素材</ContentDescription>
                <Column>
                    <ColumnName>今日世界</ColumnName>
                </Column>
            </Description>
            <Date>
                <CreateDate>2006-10-25 13:12:10</CreateDate>
            </Date>
            <Format>
                <TotalLength>00:04:35:12</TotalLength>
                <NumberofElements>2</NumberofElements>
                <MarkPoint>
                    <StartPoint>00:00:00:05</StartPoint>
                    <EndPoint>00:04:35:10</EndPoint>
                </MarkPoint>
            </Format>
        </ResourceMetaDataInfo>
</ResourceEntity>
</MREML>

    若要查找ResourceUniqueID的值,则xpath应该书写为://ML:MREML/ML:ResourceEntity/RMDI:ResourceMetaDataInfo/RMDI:ResourceID/RUI:ResourceUniqueID/text()

    这里的ML(prefix)和URI(MERML)等已经通过
if (prefix.equalsIgnoreCase("ML"))
                                    uri = "MREML";
                                else if (prefix.equalsIgnoreCase("RE"))
                                    uri = "http://herry.com.cn";
                                else if (prefix.equalsIgnoreCase("RID"))
                                    uri = "ResourceID";
                                else if (prefix.equalsIgnoreCase("RUI"))
                                    uri= "ResourceUniqueID";
                                else if (prefix.equalsIgnoreCase("RMDI"))
                                    uri = "ResourceMetaDataInfo";
                                else
uri = null;
    映射。

    其中的ML和RMDI都是default namespace,它的作用范围包含它的子元素,直至有新的default namespace出现为止。而namespace只对它自身起作用。如将上述文档中:<ResourceMetaDataInfo>
            <ResourceID xmlns="ResourceID">
改为:
<RMDI:ResourceMetaDataInfo xmlns:RMDI=” ResourceMetaDataInfo”>
            <ResourceID>


</ RMDI:ResourceMetaDataInfo>
    查找ResourceUniqueID的值,则xpath应该改为://ML:MREML/ML:ResourceEntity/RMDI:ResourceMetaDataInfo/ResourceID/RUI:ResourceUniqueID/text()

JsoupXpath 是一款纯Java开发的使用xpath解析html的解析器,xpath语法分析与执行完全独立,html的DOM树生成借助Jsoup,故命名为JsoupXpath.为了在java里也享受xpath的强大与方便但又苦于找不到一款足够强大的xpath解析器,故开发了JsoupXpath。JsoupXpath的实现逻辑清晰,扩展方便,支持几乎全部常用的xpath语法.http://www.cnblogs.com/ 为例 "//a/@href"; "//div[@id='paging_block']/div/a[text()='Next >']/@href"; "//div[@id='paging_block']/div/a[text()*='Next']/@href"; "//h1/text()"; "//h1/allText()"; "//h1//text()"; "//div/a"; "//div[@id='post_list']/div[position()1000]/div/h3/allText()"; //轴支持 "//div[@id='post_list']/div[self::div/div/div/span[@class='article_view']/a/num()>1000]/div/h3/allText()"; "//div[@id='post_list']/div[2]/div/p/preceding-sibling::h3/allText()"; "//div[@id='post_list']/div[2]/div/p/preceding-sibling::h3/allText()|//div[@id='post_list']/div[1]/div/h3/allText()"; 在这里暂不列出框架间的对比了,但我相信,你们用了会发现JsoupXpath就是目前市面上最强大的的Xpath解析器。 快速开始 如果不方便使用maven,可以直接使用lib下的依赖包跑起来试试,如方便可直接使用如下dependency(已经上传至中央maven库,最新版本0.1.1):    cn.wanghaomiao    JsoupXpath    0.1.1 依赖配置好后,就可以使用如下例子进行体验了!String xpath="//div[@id='post_list']/div[./div/div/span[@class='article_view']/a/num()>1000]/div/h3/allText()";String doc = "..."; JXDocument jxDocument = new JXDocument(doc); List<Object> rs = jxDocument.sel(xpath); for (Object o:rs){     if (o instanceof Element){             int index = ((Element) o).siblingIndex();             System.out.println(index);     }     System.out.println(o.toString()); } 其他可以参考 cn.wanghaomiao.example包下的例子 语法 支持标准xpath语法(支持谓语嵌套),支持全部常用函数,支持全部常用轴,去掉了一些标准里面华而不实的函数和轴,下面会具体介绍。语法可以参考http://www.w3school.com.cn/xpath/index.asp 关于使用Xpath的一些注意事项 非常不建议直接粘贴Firefox或chrome里生成的Xpa
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值