Openrefine:根据子节点值选择XML

时间:2017-06-23 12:52:21

标签: xml xpath openrefine

我在openrefine中有一些列包含我从Web服务获得的这种值。

<?xml version="1.0" encoding="UTF-8"?>
    <results>
        <result>
            <nnt>2010BOR30012</nnt>
            <ppn>146708164</ppn>
            <typerecord>m</typerecord>
        </result>
        <result>
            <nnt>2010BOR30012</nnt>
            <ppn>159823226</ppn>
            <typerecord>v</typerecord>
        </result>
</results>

我希望能够通过此XML获取<ppn>标记中包含的<result>值,例如<typerecord>为v。我已经尝试了基于parseHtml和select的不同的东西但是暂时我还没有找到解决方案来实现它。

更新@Tomalak的以下评论:我一直在尝试的事情主要是:

  • 尝试将parseHtml()和select()与某种xpath结合起来,我不认为这是可能的,但如果事情证明我错了,我会很高兴:)
  • 尝试遍历每个<result>并测试每个<typerecord>的子标签,使用类似的方法:forEach(value.parseHtml().select("result"), e, "<xml>" + e.replace("\n", "").replace("\/", "/") + "</xml>")我的目标是让这个forEach的最后一部分得到一些东西我我能够使用parseHtml进行解析(这就是为什么我一直试图添加周围的<xml>标签,但它不起作用,我得到类似[ "<xml><result> <nnt> 1989BOR30027 <\/nnt> <ppn> 006608523 <\/ppn> <typerecord> m <\/typerecord><\/result><\/xml>" ]的东西,由于额外的\而无法解析我无法删除。

与此同时,我找到了一种方法来解决我的问题,即使我更喜欢使用grel的解决方案,这个使用jython工作,所以我在那里添加它但是这个问题仍然对Grel的答案开放了!

所以似乎完成这项工作的jython脚本是:

from xml.etree import ElementTree as ET
element = ET.fromstring(value)

resultsList = element.findall("./result")

for result in resultsList:
    typerecord = result.find("typerecord")
    if typerecord.text == "m":
        return result.find("ppn").text

我很确定有一个更简单的解决方案,但我仍然无法找到它!

3 个答案:

答案 0 :(得分:1)

GREL中可能有许多解决方案,例如:

forEachIndex(value.parseHtml().select("typerecord"), i, v, if(v.htmlText()=="v",value.parseHtml().select("ppn")[i].htmlText(),null)).join(' ')

with(value.parseHtml().select('result'), e, filter(e.join('|').split('|'), v, v.contains('v')))[0].parseHtml().select("ppn")[0].htmlText()

forEach(value.parseHtml().select("result"),e,if(e.select("typerecord")[0].htmlText()=="v", e.select("ppn")[0].ownText(), null)).join('')

但我不喜欢这种俄罗斯娃娃。使用xml.etree在Jython中自己的解决方案更加清晰。怎么了?

答案 1 :(得分:1)

我同意Ettore - 在这种情况下,Jython将提供最简单的解决方案。但是如果你想用GREL来做我的解决方案是:

使用GREL和parseHtml 尽管它的名称,您可以使用parseHtml函数解析XML。 select函数接受jsoup选择器

value.parseHtml().select("result")

将获得所有结果元素

要仅选择包含typerecord = v的结果元素,您必须将其与过滤函数结合使用:     。过滤器(value.parseHtml()选择(&#34;导致&#34;)中,e,e.select(&#34; typerecord&#34;)[0] .ownText()==&#34; V&# 34)

这将为您提供一个结果元素数组,其中typerecord = v

所以最后你可以通过迭代来选择ppn值:

forEach(filter(value.parseHtml().select("result"),e,e.select("typerecord")[0].ownText()=="v"), f, f.select("ppn")[0].ownText())

答案 2 :(得分:0)

获取ppn节点,然后按&#34;过滤回父/ typerecord / value = v&#34;:

//result/ppn[../typerecord/text()='v']