我是xquery的新手,我正在寻找这个问题的快速解决方案。
我有一个xml文档,我想在文档中找到所有第一对堂兄弟和所有第二对堂兄弟。
请查看下面的xml,并指导我如何继续,或者您是否可以提供任何高度专业化的代码段。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE GEDCOM SYSTEM "file:/Users/indiwarafernando/Downloads/family.dtd">
<GEDCOM>
<HeaderRec>
<FileCreation Date=""></FileCreation>
<Submitter>
<Link Target="" Ref="FM001"/>
</Submitter>
</HeaderRec>
<FamilyRec Id="FM001">
<HusbFath>
<Link Target="IndividualRec" Ref="IN001"/>
</HusbFath>
<WifeMoth>
<Link Target="IndividualRec" Ref="IN002"/>
</WifeMoth>
<Child>
<Link Target="IndividualRec" Ref="IN004"/>
</Child>
<Child>
<Link Target="IndividualRec" Ref="IN007"/>
</Child>
</FamilyRec>
<FamilyRec Id="FM002">
<HusbFath>
<Link Target="IndividualRec" Ref="IN004"/>
</HusbFath>
<WifeMoth>
<Link Target="IndividualRec" Ref="IN005"/>
</WifeMoth>
<Child>
<Link Target="IndividualRec" Ref="IN006"/>
</Child>
</FamilyRec>
<FamilyRec Id="FM003">
<HusbFath>
<Link Target="IndividualRec" Ref="IN007"/>
</HusbFath>
<WifeMoth>
<Link Target="IndividualRec" Ref="IN008"/>
</WifeMoth>
<Child>
<Link Target="IndividualRec" Ref="IN009"/>
</Child>
</FamilyRec>
<IndividualRec Id="IN001">
<IndivName>Fathers name</IndivName> <!-- This tag used for father of c1 or husband of w1 -->
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="" Ref="IN002"/>
<Association>Wife</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN002"> <!-- This tag used for mother of c1 or wife of h1 -->
<IndivName>Mother s name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN001"/>
<Association>Husband</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN003"> <!-- This tag used for a child to h1 or w1 or grand son to gm1 or gf1 -->
<IndivName>Child 1 name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN001"/>
<Association>Father</Association>
</AssocIndiv>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN002"/>
<Association>Mother</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN005"> <!-- This tag used for grand mother -->
<IndivName>Grand mother's name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN004"/>
<Association>Husband</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN004"> <!-- This tag used for grand father -->
<IndivName>Grand father's name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN005"/>
<Association>Grand Father's Wife</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN006"> <!-- This tag used for a child to h1 or w1 or grand son to gm1 or gf1 -->
<IndivName>Child 1 name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN004"/>
<Association>Father</Association>
</AssocIndiv>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN005"/>
<Association>Mother</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN007"> <!-- This tag used for grand mother -->
<IndivName>Grand mother's name</IndivName>
<Gender>Female</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN008"/>
<Association>Husband</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN008"> <!-- This tag used for grand father -->
<IndivName>Grand father's name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN007"/>
<Association>Grand Father's Wife</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN009"> <!-- This tag used for a child to h1 or w1 or grand son to gm1 or gf1 -->
<IndivName>Child 1 name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN007"/>
<Association>Father</Association>
</AssocIndiv>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN008"/>
<Association>Mother</Association>
</AssocIndiv>
</IndividualRec>
</GEDCOM>
* 示例输出:* 一对第一堂兄的示例输出是 IN006和IN009
此致 法里德
答案 0 :(得分:1)
<强>予。这个XSLT 2.0转换(可以很容易地重写到XSLT 1.0中)产生所有第一代表兄弟:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:my" exclude-result-prefixes="my xs">
<xsl:output method="text"/>
<xsl:key name="kChildren" match="Child"
use="../HusbFath/*/@Ref"/>
<xsl:key name="kChildren" match="Child"
use="../WifeMoth/*/@Ref"/>
<xsl:variable name="vDoc" select="/"/>
<xsl:template match="FamilyRec">
<xsl:variable name="vGrandChildren" select=
"my:GrandChildren((HusbFath|WifeMoth)
[string(*/@Ref)][1]
/*/@Ref
)
"/>
<xsl:sequence select=
"for $first in 1 to count($vGrandChildren),
$second in $first+1 to count($vGrandChildren),
$grand1 in $vGrandChildren[$first],
$grand2 in $vGrandChildren[$second]
return
if(not($grand1/.. is $grand2/..))
then (concat('[', $grand1/*/@Ref, ',', $grand2/*/@Ref, '] '))
else ()
"/>
</xsl:template>
<xsl:template match="text()"/>
<xsl:function name="my:GrandChildren">
<xsl:param name="pRef" as="xs:string?"/>
<xsl:sequence select=
"key('kChildren',
key('kChildren', $pRef, $vDoc)/Link/@Ref,
$vDoc)
"/>
</xsl:function>
</xsl:stylesheet>
将此转换应用于提供的XML文档时:
<GEDCOM>
<HeaderRec>
<FileCreation Date=""></FileCreation>
<Submitter>
<Link Target="" Ref="FM001"/>
</Submitter>
</HeaderRec>
<FamilyRec Id="FM001">
<HusbFath>
<Link Target="IndividualRec" Ref="IN001"/>
</HusbFath>
<WifeMoth>
<Link Target="IndividualRec" Ref="IN002"/>
</WifeMoth>
<Child>
<Link Target="IndividualRec" Ref="IN004"/>
</Child>
<Child>
<Link Target="IndividualRec" Ref="IN007"/>
</Child>
</FamilyRec>
<FamilyRec Id="FM002">
<HusbFath>
<Link Target="IndividualRec" Ref="IN004"/>
</HusbFath>
<WifeMoth>
<Link Target="IndividualRec" Ref="IN005"/>
</WifeMoth>
<Child>
<Link Target="IndividualRec" Ref="IN006"/>
</Child>
</FamilyRec>
<FamilyRec Id="FM003">
<HusbFath>
<Link Target="IndividualRec" Ref="IN007"/>
</HusbFath>
<WifeMoth>
<Link Target="IndividualRec" Ref="IN008"/>
</WifeMoth>
<Child>
<Link Target="IndividualRec" Ref="IN009"/>
</Child>
</FamilyRec>
<IndividualRec Id="IN001">
<IndivName>Fathers name</IndivName>
<!-- This tag used for father of c1 or husband of w1 -->
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="" Ref="IN002"/>
<Association>Wife</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN002">
<!-- This tag used for mother of c1 or wife of h1 -->
<IndivName>Mother s name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN001"/>
<Association>Husband</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN003">
<!-- This tag used for a child to h1 or w1 or grand son to gm1 or gf1 -->
<IndivName>Child 1 name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN001"/>
<Association>Father</Association>
</AssocIndiv>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN002"/>
<Association>Mother</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN005">
<!-- This tag used for grand mother -->
<IndivName>Grand mother's name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN004"/>
<Association>Husband</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN004">
<!-- This tag used for grand father -->
<IndivName>Grand father's name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN005"/>
<Association>Grand Father's Wife</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN006">
<!-- This tag used for a child to h1 or w1 or grand son to gm1 or gf1 -->
<IndivName>Child 1 name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN004"/>
<Association>Father</Association>
</AssocIndiv>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN005"/>
<Association>Mother</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN007">
<!-- This tag used for grand mother -->
<IndivName>Grand mother's name</IndivName>
<Gender>Female</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN008"/>
<Association>Husband</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN008">
<!-- This tag used for grand father -->
<IndivName>Grand father's name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN007"/>
<Association>Grand Father's Wife</Association>
</AssocIndiv>
</IndividualRec>
<IndividualRec Id="IN009">
<!-- This tag used for a child to h1 or w1 or grand son to gm1 or gf1 -->
<IndivName>Child 1 name</IndivName>
<Gender>Male</Gender>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN007"/>
<Association>Father</Association>
</AssocIndiv>
<AssocIndiv>
<Link Target="IndividualRec" Ref="IN008"/>
<Association>Mother</Association>
</AssocIndiv>
</IndividualRec>
</GEDCOM>
产生了想要的正确结果:
[IN006,IN009]
<强> II。要测试两个Child
元素是否为第二个堂兄弟,请添加上面的(并添加必要的代码以测试每对Child
,无论它们是第二个表兄弟:
<xsl:key name="kGrandParent" match="HusbFath | WifeMoth"
use="my:GrandChildren(Link/@Ref)/*/@Ref"/>
<xsl:function name="my:areFirststCousins" as="xs:boolean">
<xsl:param name="pPers1" as="element()"/>
<xsl:param name="pPers2" as="element()"/>
<xsl:sequence select=
"key('kGrandParent', $pPers1/*/@Ref, $vDoc)[1]
is
key('kGrandParent', $pPers2/*/@Ref, $vDoc)[1]
and
not($pPers1/.. is $pPers2/..)
"/>
</xsl:function>
<xsl:function name="my:areSecondCousins" as="xs:boolean">
<xsl:param name="pPers1" as="element()"/>
<xsl:param name="pPers2" as="element()"/>
<xsl:sequence select=
"my:areFirststCousins($pPers1/../(HusbFath|WifeMoth)[1],
$pPers2/../(HusbFath|WifeMoth)[1]
)
"/>
</xsl:function>
<强> III。完整的解决方案:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:my="my:my" exclude-result-prefixes="my xs">
<xsl:output method="text"/>
<xsl:key name="kChildren" match="Child"
use="../HusbFath/*/@Ref"/>
<xsl:key name="kChildren" match="Child"
use="../WifeMoth/*/@Ref"/>
<xsl:key name="kGrandParent" match="HusbFath | WifeMoth"
use="my:GrandChildren(Link/@Ref)/*/@Ref"/>
<xsl:variable name="vDoc" select="/"/>
<xsl:template match="/*">
First Cousins:
<xsl:sequence select=
"for $first in 1 to count(/*/FamilyRec/Child),
$second in $first+1 to count(/*/FamilyRec/Child),
$pers1 in (/*/FamilyRec/Child)[$first],
$pers2 in (/*/FamilyRec/Child)[$second]
return
if(my:areFirststCousins($pers1, $pers2))
then concat('[', $pers1/*/@Ref, ',', $pers2/*/@Ref, '] ')
else ()
"/>
Second Cousins:
<xsl:sequence select=
"for $first in 1 to count(/*/FamilyRec/Child),
$second in $first+1 to count(/*/FamilyRec/Child),
$pers1 in (/*/FamilyRec/Child)[$first],
$pers2 in (/*/FamilyRec/Child)[$second]
return
if(my:areSecondCousins($pers1, $pers2))
then concat('[', $pers1/*/@Ref, ',', $pers2/*/@Ref, '] ')
else ()
"/>
</xsl:template>
<xsl:function name="my:GrandChildren">
<xsl:param name="pRef" as="xs:string?"/>
<xsl:sequence select=
"key('kChildren',
key('kChildren', $pRef, $vDoc)/Link/@Ref,
$vDoc)
"/>
</xsl:function>
<xsl:function name="my:areFirststCousins" as="xs:boolean">
<xsl:param name="pPers1" as="element()"/>
<xsl:param name="pPers2" as="element()"/>
<xsl:sequence select=
"key('kGrandParent', $pPers1/*/@Ref, $vDoc)[1]
is
key('kGrandParent', $pPers2/*/@Ref, $vDoc)[1]
and
not($pPers1/.. is $pPers2/..)
"/>
</xsl:function>
<xsl:function name="my:areSecondCousins" as="xs:boolean">
<xsl:param name="pPers1" as="element()"/>
<xsl:param name="pPers2" as="element()"/>
<xsl:sequence select=
"my:areFirststCousins($pPers1/../(HusbFath|WifeMoth)[1],
$pPers2/../(HusbFath|WifeMoth)[1]
)
"/>
</xsl:function>
</xsl:stylesheet>
将此转换应用于同一提供的XML文档(上图)时,会生成正确的结果:
First Cousins:
[IN006,IN009]
Second Cousins: