当我从 SQL Server 查询数据 AS XML 时,它通常会生成重复的 XML 节点。通常我可以调整查询以消除这种情况,但并非总是如此。对于那些我不能的时候,我最终得到了这样的 XML:
<Xml>
<House houseId="3" address="123 Main">
<Dog dogId="13" name="Rover">
<Flea fleaId="17" name="Chester" />
</Dog>
<Dog dogId="13" name="Rover">
<Flea fleaId="23" name="Poindexter" />
</Dog>
</House>
<House houseId="3" address="123 Main">
<Human humanId="9" name="Mr. Johnson">
<Child childId="11" name="Susie" />
</Human>
<Human humanId="9" name="Mr. Johnson">
<Child childId="31" name="Sandy" />
</Human>
</House>
<House houseId="5" address="987 Wall">
<Dog dogId="13" name="Rover">
<Flea fleaId="17" name="Chester" />
</Dog>
<Dog dogId="13" name="Rover">
<Flea fleaId="19" name="Wilhelm" />
</Dog>
</House>
</Xml>
请注意,有两个彼此相邻的 <House> 节点,它们的属性相同。它们仅在子节点上有所不同。我正在尝试创建一个 XSLT,它将采用相同的兄弟节点,并将它们折叠成一个包含所有子节点超集的节点。在示例中,<House houseId="3"> 将包含 <Dog> 和 <Human> 节点。像这样:
<Xml>
<House houseId="3" address="123 Main">
<Dog dogId="13" name="Rover">
<Flea fleaId="17" name="Chester" />
<Flea fleaId="23" name="Poindexter" />
</Dog>
<Human humanId="9" name="Mr. Johnson">
<Child childId="11" name="Susie" />
<Child childId="31" name="Sandy" />
</Human>
</House>
<House houseId="5" address="987 Wall">
<Dog dogId="13" name="Rover">
<Flea fleaId="17" name="Chester" />
<Flea fleaId="19" name="Wilhelm" />
</Dog>
</House>
</Xml>
不仅合并了两个相同的 House 节点,还合并了重复的 Dog 和 Human 节点。但请注意,在两个不同的 <House> 节点下列出的 <Dog dogId='13' name='Rover'> 节点并未合并,因为它们不相同。(由于他们的祖先。)这就是我想要的:组合匹配的兄弟节点。
因为 XML 是由 SQL 生成的,所以 XSLT 将处理许多不同名称和排列的节点。因此,我无法对节点名称进行硬编码。但我可以放心,每个节点都会有一个相应的 id 属性,该属性将包含一个数值。例如:<House houseId="3">、<Dog dogId="17"> 和 <Flea fleaId="13">。
我也知道根节点没有属性,所以我可以开始处理根节点的子节点。
我的策略是为每个节点创建一个 xsl:key,其中节点的键值是其祖先节点与 id 值的串联。示例键值在下面的评论中
<Xml>
<House houseId="3" address="123 Main"><!--"houseId=3"-->
<Dog dogId="13" name="Rover" ><!--"houseId=3;dogId=13"-->
<Flea fleaId="17" name="Chester" /><!--"houseId=3;dogId=13;fleaId=17"-->
</Dog>
<Dog dogId="13" name="Rover" ><!--"houseId=3;dogId=13"-->
<Flea fleaId="23" name="Poindexter" /><!--"houseId=3;dogId=13;fleaId=23"-->
</Dog>
</House>
<House houseId="3" address="123 Main" ><!--"houseId=3"-->
<Human humanId="9" name="Mr. Johnson" ><!--"houseId=3;humanId=9"-->
<Child childId="11" name="Susie" /><!--"houseId=3;humanId=9;childId=11"-->
</Human>
<Human humanId="9" name="Mr. Johnson"><!--"houseId=3;humanId=9"-->
<Child childId="31" name="Sandy" /><!--"houseId=3;humanId=9;childId=31"-->
</Human>
</House>
<House houseId="5" address="987 Wall" ><!--"houseId=5"-->
<Dog dogId="13" name="Rover"><!--"houseId=5;dogId=13"-->
<Flea fleaId="17" name="Chester" /><!--"houseId=5;dogId=13;fleaId=17"-->
</Dog>
<Dog dogId="13" name="Rover"><!--"houseId=5;dogId=13"-->
<Flea fleaId="19" name="Wilhelm" /><!--"houseId=5;dogId=13;fleaId=19"-->
</Dog>
</House>
</Xml>
因此,两个看似匹配的 <Dog dogId='13' name='Rover'> 将通过它们的祖先来区分:
<Xml><House houseId="3"><Dog dogId='13' name='Rover'>
houseId=3;dogId=13
对比
<Xml><House houseId="5"><Dog dogId='13' name='Rover'>
houseId=5;dogId=13
这样,可以组合重复(兄弟)节点。不幸的是,我很难理解如何使用 XSL 和 xslt:key 来实现它。任何帮助将不胜感激。