2015-09-08 69 views
0

我正在寻找在.NET中的XPath,其选择只是最上面的节点包含只是一个终端(无子女)节点的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(*)] 

回答

0

自己的解决方案:

.//*[count(descendant-or-self::terminal)=1] [ not(ancestor::*[count(descendant::terminal)=1]) ] 

其中terminal = *[not(*)]

第一条件[count(descendant-or-self::terminal)=1]我们选择<--项目。第二条件[ not(ancestor::*[count(descendant::terminal)=1]) ]我们选择<···项目:

A    <-- <···  A 
    B   <-- 
     C  <-- 
D     <··· 
    E   <-- <···  E 
     F  <-- 
    G   <-- <···  G 
    H   <-- <···  H 
     I  <-- 
      J <-- 

交集是{AEGH}由递归的方式想

达到推广终端项目,并去除独生子女父母的最好的方法是方法:

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 
0

出了什么问题只是//*[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/> 
% 
+0

它看起来像你正在获得无子节点。我想选择{A E G H},就像第一个后代都是独生子女的祖父母。我想指出独生子女政策的起源。 – EndingBeginningCycles

+0

嗯,我没有看到一个简单的方法来做到这一点没有递归(是节点移动1或2(或更多?)的步骤?可能更容易选择无子节点,然后使用其他代码将它们向上移动到“父”轴,直到满足其他节点(或根元素)条件。 – thrig

+0

是的,你是对的。最简单的方法似乎是通过递归方法向上移动那些无子节点。不过,我更感兴趣,并且在考虑XPath表达式时遇到了更多麻烦。 – EndingBeginningCycles

相关问题