XPath Select 最上面的节点只包含一个无子节点
XPath Select the uppermost nodes that contains just one childless node
我正在寻找 .NET 中的 XPath,它只选择 最上面的节点,其中包含 只有一个 终端(无子)节点
A <--
B
C
D
E <--
F
G <--
H <--
I
J
C, F, G, J are terminal
我想摆脱无用的嵌套项并尽可能推广终端:
C to A position; F to E position; G remains in place; ...
编辑
我想我已经接近
.//*[count(descendant-or-self::terminal)=1] [ not(ancestor::*[count(.//terminal)=1]) ]
终端可以选择
*[not(*)]
只是 //*[count(descendant-or-self::*)=1]
有什么问题吗?
% cat uppermost.xml
<R>
<A><B><C/></B></A>
<D>
<E><F/></E>
<G/>
<H><I><J/></I></H>
</D>
</R>
% xpquery '//*[count(descendant-or-self::*)=1]' uppermost.xml
<C/>
<F/>
<G/>
<J/>
%
我自己的解决方案:
.//*[count(descendant-or-self::terminal)=1] [ not(ancestor::*[count(descendant::terminal)=1]) ]
其中 terminal = *[not(*)]
第一个条件 [count(descendant-or-self::terminal)=1]
我们 select <--
项。对于第二个条件 [ not(ancestor::*[count(descendant::terminal)=1]) ]
我们 select <···
items:
A <-- <··· A
B <--
C <--
D <···
E <-- <··· E
F <--
G <-- <··· G
H <-- <··· H
I <--
J <--
交叉路口是 { A E G H } 如所愿
实现终端项提升和移除one-childparents最好的方法是通过递归的方法:
Public Sub XmlTrimOneChildParents(ByRef xE As XmlElement)
Dim xNodeList As XmlNodeList = xE.SelectNodes("./*")
Select Case xNodeList.Count
Case 0 'terminal
Case 1 'Remove And Promote Child
Dim xChild As XmlNode = xNodeList(0)
XmlTrimOneChildParents(xChild)
xE.ParentNode.InsertBefore(xChild, xE)
xE.ParentNode.RemoveChild(xE)
Case else
For Each xChild As XmlNode In xNodeList
XmlTrimOneChildParents(xChild)
Next
End Select
End Sub
我正在寻找 .NET 中的 XPath,它只选择 最上面的节点,其中包含 只有一个 终端(无子)节点
A <--
B
C
D
E <--
F
G <--
H <--
I
J
C, F, G, J are terminal
我想摆脱无用的嵌套项并尽可能推广终端:
C to A position; F to E position; G remains in place; ...
编辑
我想我已经接近
.//*[count(descendant-or-self::terminal)=1] [ not(ancestor::*[count(.//terminal)=1]) ]
终端可以选择
*[not(*)]
只是 //*[count(descendant-or-self::*)=1]
有什么问题吗?
% cat uppermost.xml
<R>
<A><B><C/></B></A>
<D>
<E><F/></E>
<G/>
<H><I><J/></I></H>
</D>
</R>
% xpquery '//*[count(descendant-or-self::*)=1]' uppermost.xml
<C/>
<F/>
<G/>
<J/>
%
我自己的解决方案:
.//*[count(descendant-or-self::terminal)=1] [ not(ancestor::*[count(descendant::terminal)=1]) ]
其中 terminal = *[not(*)]
第一个条件 [count(descendant-or-self::terminal)=1]
我们 select <--
项。对于第二个条件 [ not(ancestor::*[count(descendant::terminal)=1]) ]
我们 select <···
items:
A <-- <··· A
B <--
C <--
D <···
E <-- <··· E
F <--
G <-- <··· G
H <-- <··· H
I <--
J <--
交叉路口是 { A E G H } 如所愿
实现终端项提升和移除one-childparents最好的方法是通过递归的方法:
Public Sub XmlTrimOneChildParents(ByRef xE As XmlElement)
Dim xNodeList As XmlNodeList = xE.SelectNodes("./*")
Select Case xNodeList.Count
Case 0 'terminal
Case 1 'Remove And Promote Child
Dim xChild As XmlNode = xNodeList(0)
XmlTrimOneChildParents(xChild)
xE.ParentNode.InsertBefore(xChild, xE)
xE.ParentNode.RemoveChild(xE)
Case else
For Each xChild As XmlNode In xNodeList
XmlTrimOneChildParents(xChild)
Next
End Select
End Sub