Excel的FILTERXML
使用XPATH 1.0
,这意味着它的多样性不如我们所希望的那么丰富。此外,Excel似乎不允许返回重新处理的节点值,并且仅允许按照出现顺序选择节点。但是,我们仍然可以利用相当数量的函数。更多信息可以在此处找到:这里。
该函数需要两个参数:=FILTERXML(<一个有效的XML格式字符串>,<一个有效的XPATH格式字符串>)
假设单元格A1
包含字符串:ABC|123|DEF|456|XY-1A|ZY-2F|XY-3F|XY-4f|xyz|123
。为了创建一个有效的XML字符串,我们使用SUBSTITUTE
将分隔符更改为有效的结束和开始标记结构。因此,为了针对给定示例获得有效的XML结构,我们可以执行以下操作:
"<t><s>"&SUBSTITUTE(A1,"|","</s><s>")&"</s></t>"
出于可读性的原因,我将使用单词<XML>
作为占位符来引用上述结构。以下是在有效结构中过滤节点的不同有用的XPATH
函数:
1) 所有元素:
=FILTERXML(<XML>,"//s")
返回:ABC
、123
、DEF
、456
、XY-1A
、ZY-2F
、XY-3F
、XY-4f
、xyz
和123
(所有节点)
2) 位置选择元素:
=FILTERXML(<XML>,"//s[position()=4]")
或:
=FILTERXML(<XML>,"//s[4]")
< p > < sub >返回:< code >456< /code >(第4个节点)< /sub >< sup >†< /sup >< /p >
=FILTERXML(<XML>,"//s[position()<4]")
返回:ABC
、123
和 DEF
(索引小于 4 的节点)
=FILTERXML(<XML>,"//s[position()=2 or position()>5]")
返回: 123
, ZY-2F
, XY-3F
, XY-4f
, xyz
和123
(在索引2或大于5的节点)
=FILTERXML(<XML>,"//s[last()]")
返回:123
(最后一个索引上的节点)
=FILTERXML(<XML>,"//s[position() mod 2 = 1]")
返回:ABC
、DEF
、XY-1A
、XY-3F
和 xyz
(奇数节点)
=FILTERXML(<XML>,"//s[position() mod 2 = 0]")
返回:123
、456
、ZF-2F
、XY-4f
和123
(偶数节点)
3)(非)数字元素:
=FILTERXML(<XML>,"//s[number()=.]")
或者:
=FILTERXML(<XML>,"//s[.*0=0]")
返回:123
、456
和123
(数字节点)
=FILTERXML(<XML>,"//s[not(number()=.)]")
或者:
=FILTERXML(<XML>,"//s[.*0!=0)]")
返回:ABC
、DEF
、XY-1A
、ZY-2F
、XY-3F
、XY-4f
和 xyz
(非数字节点)
4) 包含(不包含)元素:
=FILTERXML(<XML>,"//s[contains(., 'Y')]")
返回:XY-1A
、ZY-2F
、XY-3F
和 XY-4f
(包含“Y”,注意 XPATH
区分大小写,排除 xyz
)。
=FILTERXML(<XML>,"//s[not(contains(., 'Y'))]")
返回:ABC
、123
、DEF
、456
、xyz
和123
(不包括‘Y’,注意XPATH
区分大小写,包括xyz
)
5) 以(不以)某些元素开头或/和结尾:
=FILTERXML(<XML>,"//s[starts-with(., 'XY')]")
返回:XY-1A
、XY-3F
和XY-4f
(以“XY”开头)
=FILTERXML(<XML>,"//s[not(starts-with(., 'XY'))]")
返回:ABC
、123
、DEF
、456
、ZY-2F
、xyz
和 123
(不以“XY”开头)
=FILTERXML(<XML>,"//s[substring(., string-length(.) - string-length('F') +1) = 'F']")
返回:DEF
、ZY-2F
和 XY-3F
(以“F”结尾,注意XPATH 1.0
不支持ends-with
)
=FILTERXML(<XML>,"//s[not(substring(., string-length(.) - string-length('F') +1) = 'F')]")
返回:ABC
,123
,456
,XY-1A
,XY-4f
,xyz
和123
(不以“F”结尾)
=FILTERXML(<XML>,"//s[starts-with(., 'X') and substring(., string-length(.) - string-length('A') +1) = 'A']")
返回:XY-1A
(以“X”开头,以“A”结尾)
6)大写或小写的元素:
=FILTERXML(<XML>,"//s[translate(.,'abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')=.]")
返回:ABC
,123
,DEF
,456
,XY-1A
,ZY-2F
,XY-3F
和123
(大写节点)
=FILTERXML(<XML>,"//s[translate(.,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')=.]")
返回值: 123
, 456
, xyz
和 123
(小写节点)
注意: 不幸的是,XPATH 1.0
不支持 upper-case()
和 lower-case()
,所以上述内容是一个解决方法。如有需要,请添加特殊字符。
7) 包含或不包含任何数字的元素:
=FILTERXML(<XML>,"//s[translate(.,'1234567890','')!=.]")
返回:123
、456
、XY-1A
、ZY-2F
、XY-3F
、XY-4f
和包含任何数字的123
=FILTERXML(<XML>,"//s[translate(.,'1234567890','')=.]")
返回:ABC
,DEF
和xyz
(不包含任何数字)
=FILTERXML(<XML>,"//s[translate(.,'1234567890','')!=. and .*0!=0]")
返回:XY-1A
、ZY-2F
、XY-3F
和 XY-4f
(保留数字但不作为单独的数字存在)
8)唯一元素或重复元素:
=FILTERXML(<XML>,"//s[preceding::*=.]")
返回:123
(重复节点)
=FILTERXML(<XML>,"//s[not(preceding::*=.)]")
返回:ABC
、123
、DEF
、456
、XY-1A
、ZY-2F
、XY-3F
、XY-4f
和xyz
(唯一节点)
=FILTERXML(<XML>,"//s[not(following::*=. or preceding::*=.)]")
返回:ABC
、DEF
、456
、XY-1A
、ZY-2F
、XY-3F
和XY-4f
(没有类似兄弟节点的节点)
9) 特定长度的元素:
=FILTERXML(<XML>,"//s[string-length()=5]")
返回:XY-1A
,ZY-2F
,XY-3F
和XY-4f
(长度为5个字符)
=FILTERXML(<XML>,"//s[string-length()<4]")
返回:ABC
,123
,DEF
,456
,xyz
和短于4个字符的123
10) 基于前面/后面的元素:
=FILTERXML(<XML>,"//s[preceding::*[1]='456']")
返回: XY-1A
(上一个节点为'456')
=FILTERXML(<XML>,"//s[starts-with(preceding::*[1],'XY')]")
返回:ZY-2F
、XY-4f
和xyz
(前一个节点以“XY”开头)
=FILTERXML(<XML>,"//s[following::*[1]='123']")
返回:ABC
和xyz
(后续节点等于'123')
=FILTERXML(<XML>,"//s[contains(following::*[1],'1')]")
返回:ABC
,456
和xyz
(以下节点包含“1”)
=FILTERXML(<XML>,"//s[preceding::*='ABC' and following::*='XY-3F']")
或者:
=FILTERXML(<XML>,"//s[.='ABC']/following::s[following::s='XY-3F']")
返回:123
,DEF
,456
,XY-1A
和ZY-2F
(在“ABC”和“XY-3F”之间的所有内容)
11)基于子字符串的元素:
=FILTERXML(<XML>,"//s[substring-after(., '-') = '3F']")
返回:XY-3F
(连字符后面以“3F”结尾的节点)
=FILTERXML(<XML>,"//s[contains(substring-after(., '-') , 'F')]")
返回:ZY-2F
和XY-3F
(包含连字符后面有 'F' 的节点)
=FILTERXML(<XML>,"//s[substring-before(., '-') = 'ZY']")
返回:ZY-2F
(连字符前以“ZY”开头的节点)
=FILTERXML(<XML>,"//s[contains(substring-before(., '-'), 'Y')]")
返回:XY-1A
、ZY-2F
、XY-3F
和XY-4f
(节点包含连字符前面的“Y”)
12) 基于连接的元素:
=FILTERXML(<XML>,"//s[concat(., '|', following::*[1])='ZY-2F|XY-3F']")
返回:ZY-2F
(与 '|' 连接并且其后续同级节点为 'ZY-2F|XY-3F' 时的节点)
=FILTERXML(<XML>,"//s[contains(concat(., preceding::*[2]), 'FA')]")
返回:DEF
(与左侧两个同级节点连接时包含“FA”的节点)
13)空 vs. 非空:
=FILTERXML(<XML>,"//s[count(node())>0]")
或:
=FILTERXML(<XML>,"//s[node()]")
返回:ABC
、123
、DEF
、456
、XY-1A
、ZY-2F
、XY-3F
、XY-4f
、xyz
和 123
(所有非空节点)
=FILTERXML(<XML>,"//s[count(node())=0]")
或:
=FILTERXML(<XML>,"//s[not(node())]")
返回值:None(所有为空的节点)
14)前驱或后继:
=FILTERXML(<XML>,"//s[substring(., string-length(.) - string-length('F') +1) = 'F'][last()]/following::*")
返回:XY-4f
、xyz
和123
(所有以大写字母'F'结尾的最后一个节点右侧的所有节点)
=FILTERXML(<XML>,"//s[substring(., string-length(.) - string-length('F') +1) = 'F'][1]/preceding::*")
返回:ABC
和123
(所有节点位于以大写字母'F'结尾的第一个节点左侧)
15)(前置或后置)和self:
=FILTERXML(<XML>,"(//s[.*0!=0][last()]|//s[.*0!=0][last()]/preceding::*)")
返回:ABC
,123
,DEF
,456
,XY-1A
,ZY-2F
,XY-3F
,XY-4f
和xyz
(从右侧删除所有数字节点)††
=FILTERXML(<XML>,"(//s[.*0=0][1]|//s[.*0=0][1]/following::*)")
Returns:
123
,
DEF
,
456
,
XY-1A
,
ZY-2F
,
XY-3F
,
XY-4f
,
xyz
and
123
(trim all non-numeric nodes from the left)。
16) 最大值或最小值:=FILTERXML(<XML>,"(//s[.*0=0][not(.<//s[.*0=0])])[1]")
返回:456
(查看数字节点时的最大值)
=FILTERXML(<XML>,"(//s[.*0=0][not(.>//s[.*0=0])])[1]")
返回:123
(查看数值节点的最小值)
注意:这相当于根据#3返回所有数值节点,然后使用Excel的MIN()
和MAX()
函数对数组进行后处理。
显然,以上是展示XPATH 1.0
函数可能性的一个演示,您可以获得各种组合及更多内容!我试图涵盖大多数常用的字符串函数。如果您缺少任何内容,请随时评论。
虽然问题本身很广泛,但我希望提供一些有关如何使用FILTERXML
查询的一般方向。该公式返回要在其他任何方式中使用的节点数组。很多时候我会在TEXTJOIN()
或INDEX()
中使用它。但是我想其他选项将是新的DA函数来溢出结果。
请注意,在通过FILTERXML()
解析字符串时,和号字符(&)和左角括号(<)必须不以其文字形式出现。不。它们分别需要用&
或<
替换。另一个选项是使用它们的数字ISO/IEC 10646字符代码分别为&
或<
。解析后,该函数将以其文字形式返回这些字符。不用说,通过半冒号拆分字符串因此变得棘手。
‡每个谓词,即打开和关闭方括号之间的结构,都是给定节点列表的过滤器。编写多个这些结构实际上是anding这样的谓词。
‡‡没有真正的易于遵循/前面的兄弟< strong>和自我结构。因此,我使用了联合运算符。但是 ,这需要将多个表达式放在括号内。如果考虑正则表达式中的捕获组内的交替,则与之类似。
FilterXML
将数字字符串转换为排序后的唯一数字数组的巧妙方法感兴趣。该方法在将数字划分为唯一排序数字 的帖子中进行了解释,并提供了一些说明和链接(以及上述帖子的链接)。- @JvdV - T.M.=FILTERXML(<XML>,"//s[.<200]")
,它将返回两个“123”节点。 - JvdVFILTERXML()
。非常感谢你。 - Harun24hr