Openrefine: select XML 基于子节点值
Openrefine: select XML based on child node value
我在 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 获得包含在 <result>
标记中的 <ppn>
值,例如,其中 <typerecord>
是 v。我尝试了基于 parseHtml 和 select 的不同方法,但目前我还没有找到解决方案来实现它。
更新@Tomalak 的评论:我一直在尝试的主要是:
- 尝试将 parseHtml() 和 select() 与某种 xpath 相结合,我不认为这是可能的,但如果有什么能证明我错了,我会很高兴:)
- 尝试遍历每个
<result>
并针对子标签 <typerecord>
测试每个我可以使用 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
我很确定有更简单的解决方案,但我仍然找不到它!
获取ppn节点,然后按"back to parent / typerecord / value=v"过滤:
//result/ppn[../typerecord/text()='v']
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('')
但是我不喜欢这种俄罗斯套娃。您自己在 Jython 中使用 xml.etree
的解决方案更加清晰。怎么了?
我同意 Ettore 的观点 - 在这种情况下,Jython 将提供最简单的解决方案。但是如果你想用 GREL 来做,我的解决方案是:
使用 GREL 和 parseHtml
尽管有它的名字,但您可以使用 parseHtml 函数解析 XML。 select 函数接受 jsoup select 或
value.parseHtml().select("result")
会得到所有的结果元素
要select 只有包含 typerecord=v 的结果元素,您必须将其与过滤函数结合使用:
filter(value.parseHtml().select("result"),e,e.select("typerecord")[0].ownText()=="v")
这将为您提供一个结果元素数组,其中 typerecord=v
所以最后你可以通过这些迭代到 select ppn 值:
forEach(filter(value.parseHtml().select("result"),e,e.select("typerecord")[0].ownText()=="v"), f, f.select("ppn")[0].ownText())
我在 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 获得包含在 <result>
标记中的 <ppn>
值,例如,其中 <typerecord>
是 v。我尝试了基于 parseHtml 和 select 的不同方法,但目前我还没有找到解决方案来实现它。
更新@Tomalak 的评论:我一直在尝试的主要是:
- 尝试将 parseHtml() 和 select() 与某种 xpath 相结合,我不认为这是可能的,但如果有什么能证明我错了,我会很高兴:)
- 尝试遍历每个
<result>
并针对子标签<typerecord>
测试每个我可以使用 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
我很确定有更简单的解决方案,但我仍然找不到它!
获取ppn节点,然后按"back to parent / typerecord / value=v"过滤:
//result/ppn[../typerecord/text()='v']
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('')
但是我不喜欢这种俄罗斯套娃。您自己在 Jython 中使用 xml.etree
的解决方案更加清晰。怎么了?
我同意 Ettore 的观点 - 在这种情况下,Jython 将提供最简单的解决方案。但是如果你想用 GREL 来做,我的解决方案是:
使用 GREL 和 parseHtml 尽管有它的名字,但您可以使用 parseHtml 函数解析 XML。 select 函数接受 jsoup select 或
value.parseHtml().select("result")
会得到所有的结果元素
要select 只有包含 typerecord=v 的结果元素,您必须将其与过滤函数结合使用: filter(value.parseHtml().select("result"),e,e.select("typerecord")[0].ownText()=="v")
这将为您提供一个结果元素数组,其中 typerecord=v
所以最后你可以通过这些迭代到 select ppn 值:
forEach(filter(value.parseHtml().select("result"),e,e.select("typerecord")[0].ownText()=="v"), f, f.select("ppn")[0].ownText())