首先,我们需要知道是什么是要解决的问题。比如,家庭成员树为XML文档和概念提供了一个很好的例子。问题就是:你不可能用XML文档来表达完整的家庭成员树,因为一个XML文件只能有一个根节点(或者最终父节点),而一个人常常有两个父辈。
但是我们可以定义一个虚拟的根,来包含这两个最终父节点,如这样考虑:
<TheSmiths>通过这个方法,你就可以列出所有Smith家族的子女,他们的孙子女和他们的曾孙子女等等。但是,如果我们稍微改变一些思路,结果会如何呢?
<JohnSmith>
<BettySmith>
</TheSmiths>
如果不从最终根节点的视角来考虑这棵关系树,而从最终子节点的视角来看这个问题会如何呢?一个父节点所引发的问题是:它把我们限制在单先辈节点。当我们发现有更多的先辈时,我们就遇到问题了。
另外一个解决家庭成员树问题的方法是:改变我们对XML层次的看法。让我们把家庭先辈当成XML子孙,而不是XML先辈。
我们看下面这个XML文档例子,它演示了这个技术。列表1列出了一个虚构的John Smith的先辈。
列表1:johnsmith.xml
<?xml version="1.0" ?> <JohnSmith> <JeffersonSmith> <WilliamSmith> <RichardSmith> </RichardSmith> <AdelaideBrooksSmith> </AdelaideBrooksSmith> </WilliamSmith> <RebeccaCorruthersSmith> <GeorgeCorruthers> </GeorgeCorruthers> <SvetlanaMironovCorruthers> </SvetlanaMironovCorruthers> </RebeccaCorruthersSmith> </JeffersonSmith> <DeloresJonesSmith> <ArchibaldJones> <BenjaminJones> <ArthurJones> </ArthurJones> <PauletteBoudinJones> </PauletteBoudinJones> </BenjaminJones> <ElizabethBennettJones> <GeoffreyBennett> </GeoffreyBennett> <BeatriceBennettBaughman> </BeatriceBennettBaughman> </ElizabethBennettJones> </ArchibaldJones> <WilmaStockhausenJones> <GuntherStockhausen> </GuntherStockhausen> <UlmaWeinerbraugStockhausen> </UlmaWeinerbraugStockhausen> </WilmaStockhausenJones> </DeloresJonesSmith> </JohnSmith>
我们的文档例子有一个叫John Smith的根元素,你看到的就是他的先辈们。而从XML层次来说,也是他的“孩子们”。这个文档中的每个父节点有两个子节点,他们代表了父节点的父辈。仍然很疑惑吗?下面是简单的演示。
<person>
<mom/>
<dad/>
</person>
每个人的子元素实际上是他们的父辈。每个父元素实际上是他们的子女。我们已经把文档转化得能让我们更清晰地看到John Smith的先辈了。
我们刚做的就是一个解决此类问题的主要方法。当然,我们的新方法有它的缺点。比如,不能同时表达出祖辈的同胞。但是,它表达了直接先辈这条线,他们可以很容易地作为子节点遍历。你也可以像你看到的第一个例子一样加入先辈到这个模型而不会打乱你的XPath声明。