ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: 象山海鲜

[原创] 强大的FILTERXML——文本处理函数(完结)

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2019-8-7 23:16 | 显示全部楼层
本帖已被收录到知识树中,索引项:FILTERXML
象山海鲜 发表于 2019-8-7 17:21
我的也不一定是最佳的。可以不看答案,先做题哈,然后还可以互相学习。

我的天呐,这个社会要是多几个像哥哥这样的银才,赶超英美就可以缩短好几十年呀。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-8-8 09:47 | 显示全部楼层
老师,高阶套路1中大于90分的为什么不能以下写法?
=FILTERXML("<a><"&SUBSTITUTE(SUBSTITUTE(B2,",","'/><"),"="," c='")&"'/></a>","//*[@c>90]")

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-8-8 09:54 | 显示全部楼层
本帖最后由 象山海鲜 于 2019-8-8 09:57 编辑
liu2336904 发表于 2019-8-8 09:47
老师,高阶套路1中大于90分的为什么不能以下写法?
=FILTERXML("

能提取的只有两种,一种是属性值,一种是节点的文本内容~!
你的公式是提取文本内容,空文本啊.....——你的愿意可能是提取元素名,元素名可以在[]谓词内name()提取并判断,但是不能出来~!!。
我猜你是想提取分数的话
  1. =FILTERXML("<a><"&SUBSTITUTE(SUBSTITUTE(B2,",","'/><"),"="," c='")&"'/></a>","//@*[.>90]")
复制代码

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-8-8 10:04 | 显示全部楼层
象山海鲜 发表于 2019-8-8 09:54
能提取的只有两种,一种是属性值,一种是节点的文本内容~!
你的公式是提取文本内容,空文本啊.....—— ...

好的,,本来是准备提取元素名的,混淆啦。。。。
现在搞清楚了,谢谢老师!!!

TA的精华主题

TA的得分主题

发表于 2019-8-8 10:55 | 显示全部楼层
本帖最后由 轩檐 于 2019-8-8 11:11 编辑

去重一:
  1. =FILTERXML("<a><b>"&SUBSTITUTE($B$301,",","</b><b>")&"</b></a>","a/b[self::b !=(preceding::b=.+0)]")
复制代码


去重二:
  1. =FILTERXML("<a><b>"&SUBSTITUTE($B$301,",","</b><b>")&"</b></a>","a/b[self::b !=(following::b=.+0)]")
复制代码


老师的公式,用的是not(prec.....)。preceding::*=.+0可以遍历数据,得出1;51;1,加not就是结果。
我在老师的基础上,变通了下,用self全选,然后减去遍历。
同理,去重三
  1. a/b[self::b !=(preceding::b=.+0 or following::b=.+0)]
复制代码

补充一下,之前不会找多个最大值,最小值等,突然相同了,就是用"a/b[self::b = not(.<../b)]"找多个最大值,思路:全选属性=最大值属性,得出几个同样的最大值。最小值也是如此。老师可以用您在预设答案的公式里求证下,即:
  1. =FILTERXML("<a><b>"&SUBSTITUTE($B$301,",","</b><b>")&"</b></a>","a/b[self::b = not(.<../b)]")
复制代码



TA的精华主题

TA的得分主题

 楼主| 发表于 2019-8-8 12:52 | 显示全部楼层

我和老师的想法有点不一样,
[] 谓词内的就是历遍当前节点集,所以self就是历遍到的当前节点,只有一个节点,不是集合,这里可以用 " . ",可以用count(self::b)=1 检测 。
[] 的就是当前节点集的每个节点都要求检测一遍的意思。
假设xml为 :
<a>
  <b>1</b>
  <b>2</b>
  <b>3</b>
  <b>4</b>
</a>
1. a/b = b元素的节点集合,{a/b[1],a/b[2],a/b[3],a/b[4]}为了理解理解就当是一个值的集合{1,2,3,4},
2. a/b[.>1] ={a/b[1][1>1],a/b[2][2>1],a/b[3][3>1],a/b[4][4>1]}
=》{a/b[2],a/b[3],a/b[4]}=>{2,3,4}
在[]里,这个集合每个值都历遍一次
-************************************---------
=FILTERXML("<a><b>"&SUBSTITUTE($B$301,",","</b><b>")&"</b></a>","a/b[self::b = not(.<../b)]")
老师的xpath a/b[self::b = not(.<../b)] ,我的解读为:
1.    a/b       ==》a根节点下的b节点集
2.   self::b   ==》b节点历遍时当前的节点
3.   ../b       ==》当前节点的的父节点下的b节点集合,这里就是a/b
4.   .<../b    ==》当前节点是否有比b节点集合小的值存在(因为比较大小,必须转为数值),只要有一个存在就返回true,否则返回false
5.   not(.<../b) ==》非运算,如果第4点的结果为true,返回false,反之则相反。
6.   self::b = not(.<../b)  ==》结果推导  
  1). self::b = true()  ==> true()=true() ==>true()。
  2). self::b = false() ==> true()=false() ==>false()。
奇怪吧,为什么这样推导,
    在等号 、 大于、小于、大于等于、小于等于时,尽量把两头的数据类型转换为一致
    not(.<../b) 的结果肯定是逻辑值,所以会试着把 self::b 转为逻辑值
    因为集合里面出来一个节点self::b,是真实存在的,所以self::b 始终返回true()


愚见:实际上就是self::b不是集合,只是当前的一个节点,在这个公式内加不加都没有任何关系。
请老师指点~。

评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-8-8 13:44 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
老师解释的很详细,在self::b =not()的处理上,的确又是多余。
以1;2;5;6;999;-3;-999;999;4;7;8;9;-3;1;4;2;-5这组数据为例,取最大和最小值时,不管有无多个,not(.<../b)都可以得出多个数据,加self完全是多余。
我原本的意思,是想用self对于当前节点的遍历,跟not的结合,得出不同的结果,是考虑到用self::b=?。
比如说:self::b=-3,结果是两个-3,所以,就用了self::b=not(.<../b),这里忽略了not本身的属性。
另外,比如说去掉最大值,最小值这些,利用self::b的!=,也是可以解决一些问题的。
上图了应该不会被抓了吧,谢谢老师耐心解答。
eh3.png
eh2.png
eh1.png

TA的精华主题

TA的得分主题

发表于 2019-8-8 14:17 | 显示全部楼层
本帖最后由 liu2336904 于 2019-8-8 14:22 编辑

海鲜老师,我觉得你XPath轴中关于child的举例不太恰当,它的用法应该是和parent相对的。
例子也应该是类似以下方式大家好理解一些!      AAA/child::*   等价于   AAA/*

捕获.PNG

评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-8-8 14:50 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
轩檐 发表于 2019-8-8 13:44
老师解释的很详细,在self::b =not()的处理上,的确又是多余。
以1;2;5;6;999;-3;-999;999;4;7;8;9;-3;1;4 ...

../b就是全部,  一个点.代表全部元素的一个,可能是这样理解好一点
filterxml比较.png

评分

2

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-8-8 15:15 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
轩檐 发表于 2019-8-8 13:44
老师解释的很详细,在self::b =not()的处理上,的确又是多余。
以1;2;5;6;999;-3;-999;999;4;7;8;9;-3;1;4 ...

我的意思
self::b != 抛开属性问题,那就是 .!=,就是文本内容比较。
如果考虑逻辑属性 就是 false()=  也可以 0= 就是逻辑值比较
例子最大值 xpath:a/b[not(/a/b>.)>.*0]
也就是前面的not(/a/b>.)逻辑值和数值 .*0 比较大小,逻辑值先转为数值1 或 0,再比较的。

我的最后意思还是[]里面比较后,不存在节点集合,只有一个逻辑值 或者 数值
如果是逻辑值,那么针对当前节点有效,
如果是数值,虽然历遍还是一样,最后提取是按照数值的位置来的~!
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-12-22 21:51 , Processed in 0.034897 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表