我想使用xslt(主键PK和外键FK)在xml中创建父元素和子元素之间的关系。源xml看起来像这样:
<root>
<Patient>
<Fname>John</Fname>
<Lname>Doe</Lname>
<Record>F00025</Record>
<Disease>
<Date>3/3/2009</Date>
<Dcode>D0456</Dcode>
<Comm>comment</Comm>
<Medicine>
<Mcode>M00025</Mcode>
<Qnt>0.01</Qnt>
<Unit>l</Unit>
</Medicine>
</Disease>
<Disease>
<Date>3/15/2009</Date>
<Dcode>D4415</Dcode>
<Comm></Comm>
</Disease>
<Disease>
<Date>3/19/2009</Date>
<Dcode>D0176</Dcode>
<Comm></Comm>
<Medicine>
<Mcode>M00015</Mcode>
<Qnt>10</Qnt>
<Unit>ml</Unit>
</Medicine>
<Medicine>
<Mcode>M00006</Mcode>
<Qnt>1</Qnt>
<Unit>m</Unit>
<Icode>
<Num>803125</Num>
<Num>803005</Num>
</Icode>
</Medicine>
</Disease>
</Patient>
<Patient>
<Fname>Jayne</Fname>
<Lname>Joyce</Lname>
<Record>F00156</Record>
<Disease>
<Date>3/18/2009</Date>
<Dcode>D3266</Dcode>
<Comm></Comm>
<Medicine>
<Mcode>M00006</Mcode>
<Qnt>1</Qnt>
<Unit>m</Unit>
<Icode>
<Num>803125</Num>
</Icode>
</Medicine>
</Disease>
</Patient>
</root>
转换后的XML应如下所示:
<root>
<Patient>
<Patient_PK>1</Patient_PK>
<Fname>John</Fname>
<Lname>Doe</Lname>
<Record>F00025</Record>
<Disease>
<Disease_PK>1</Disease_PK>
<Patient_FK>1</Patient_FK>
<Date>3/3/2009</Date>
<Dcode>D0456</Dcode>
<Comm>comment</Comm>
<Medicine>
<Medicine_PK>1</Medicine_PK>
<Disease_FK>1</Disease_FK>
<Mcode>M00025</Mcode>
<Qnt>0.01</Qnt>
<Unit>l</Unit>
</Medicine>
</Disease>
<Disease>
<Disease_PK>2</Disease_PK>
<Patient_FK>1</Patient_FK>
<Date>3/15/2009</Date>
<Dcode>D4415</Dcode>
<Comm></Comm>
</Disease>
<Disease>
<Disease_PK>3</Disease_PK>
<Patient_FK>1</Patient_FK>
<Date>3/19/2009</Date>
<Dcode>D0176</Dcode>
<Comm></Comm>
<Medicine>
<Medicine_PK>2</Medicine_PK>
<Disease_FK>3</Disease_FK>
<Mcode>M00015</Mcode>
<Qnt>10</Qnt>
<Unit>ml</Unit>
</Medicine>
<Medicine>
<Medicine_PK>3</Medicine_PK>
<Disease_FK>3</Disease_FK>
<Mcode>M00006</Mcode>
<Qnt>1</Qnt>
<Unit>m</Unit>
<Icode>
<Medicine_FK>3</Medicine_FK>
<Num>803125</Num>
<Num>803005</Num>
</Icode>
</Medicine>
</Disease>
</Patient>
<Patient>
<Patient_PK>2</Patient_PK>
<Fname>Jayne</Fname>
<Lname>Joyce</Lname>
<Record>F00156</Record>
<Disease>
<Disease_PK>4</Disease_PK>
<Patient_FK>2</Patient_FK>
<Date>3/18/2009</Date>
<Dcode>D3266</Dcode>
<Comm></Comm>
<Medicine>
<Medicine_PK>4</Medicine_PK>
<Disease_FK>4</Disease_FK>
<Mcode>M00006</Mcode>
<Qnt>1</Qnt>
<Unit>m</Unit>
<Icode>
<Medicine_FK>4</Medicine_FK>
<Num>803125</Num>
</Icode>
</Medicine>
</Disease>
</Patient>
</root>
这是我到目前为止只是通过搜索这个网站所做的,但我是XSLT的新手,所以我被困了。我认为我的主键是正确的,但外国是问题,有些不对劲。有没有更好的方法将创建的主键复制到子元素?
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method='xml' version='1.0' encoding='UTF-8' indent='yes' />
<xsl:template match="/ | @* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Patient">
<xsl:variable name="PK">
<xsl:number level="any" count="Patient"/>
</xsl:variable>
<xsl:copy>
<Patient_PK>
<xsl:value-of select="$PK"/>
</Patient_PK>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Disease">
<xsl:variable name="PK">
<xsl:number level="any" count="Disease"/>
</xsl:variable>
<xsl:variable name="FK"
select="count(../preceding-sibling::*) + 1"/>
<xsl:copy>
<Disease_PK>
<xsl:value-of select="$PK"/>
</Disease_PK>
<Patient_FK>
<xsl:value-of select="$FK"/>
</Patient_FK>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Medicine">
<xsl:variable name="PK">
<xsl:number level="any" count="Medicine"/>
</xsl:variable>
<xsl:variable name="FK"
select="count(../preceding-sibling::*) + 1"/>
<xsl:copy>
<Medicine_PK>
<xsl:value-of select="$PK"/>
</Medicine_PK>
<Disease_FK>
<xsl:value-of select="$FK"/>
</Disease_FK>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Icode">
<xsl:variable name="PK">
<xsl:number level="any" count="Icode"/>
</xsl:variable>
<xsl:variable name="FK"
select="count(../preceding-sibling::*) + 1"/>
<xsl:copy>
<Icode_PK>
<xsl:value-of select="$PK"/>
</Icode_PK>
<Medicine_FK>
<xsl:value-of select="$FK"/>
</Medicine_FK>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:1)
以下是解决方案:
<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="xs my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vPatients" as="element()*">
<xsl:for-each-group select="/*/Patient/Record" group-by=".">
<p k="{position()}">
<xsl:sequence select="."/>
</p>
</xsl:for-each-group>
</xsl:variable>
<xsl:variable name="vDiseases" as="element()*">
<xsl:for-each-group select="/*/Patient/Disease" group-by="Dcode">
<d k="{position()}">
<xsl:sequence select="Dcode"/>
</d>
</xsl:for-each-group>
</xsl:variable>
<xsl:variable name="vMedicines" as="element()*">
<xsl:for-each-group select="/*/Patient/Disease/Medicine" group-by="Mcode">
<m k="{position()}">
<xsl:sequence select="Mcode"/>
</m>
</xsl:for-each-group>
</xsl:variable>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Patient">
<Patient>
<Patient_PK><xsl:sequence select="my:PK($vPatients, Record)"/></Patient_PK>
<xsl:apply-templates/>
</Patient>
</xsl:template>
<xsl:template match="Disease">
<Disease>
<Disease_PK><xsl:sequence select="my:PK($vDiseases, Dcode)"/></Disease_PK>
<Patient_FK><xsl:sequence select="my:PK($vPatients, ../Record)"/></Patient_FK>
<xsl:apply-templates/>
</Disease>
</xsl:template>
<xsl:template match="Medicine">
<Medicine>
<Medicine_PK><xsl:sequence select="my:PK($vMedicines, Mcode)"/></Medicine_PK>
<Disease_FK><xsl:sequence select="my:PK($vDiseases, ../Dcode)"/></Disease_FK>
<xsl:apply-templates/>
</Medicine>
</xsl:template>
<xsl:function name="my:PK" as="xs:string">
<xsl:param name="pCodes" as="element()*"/>
<xsl:param name="pThis" as="xs:string"/>
<xsl:sequence select="$pCodes[*[1] eq $pThis]/@k"/>
</xsl:function>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<root>
<Patient>
<Fname>John</Fname>
<Lname>Doe</Lname>
<Record>F00025</Record>
<Disease>
<Date>3/3/2009</Date>
<Dcode>D0456</Dcode>
<Comm>comment</Comm>
<Medicine>
<Mcode>M00025</Mcode>
<Qnt>0.01</Qnt>
<Unit>l</Unit>
</Medicine>
</Disease>
<Disease>
<Date>3/15/2009</Date>
<Dcode>D4415</Dcode>
<Comm></Comm>
</Disease>
<Disease>
<Date>3/19/2009</Date>
<Dcode>D0176</Dcode>
<Comm></Comm>
<Medicine>
<Mcode>M00015</Mcode>
<Qnt>10</Qnt>
<Unit>ml</Unit>
</Medicine>
<Medicine>
<Mcode>M00006</Mcode>
<Qnt>1</Qnt>
<Unit>m</Unit>
<Icode>
<Num>803125</Num>
<Num>803005</Num>
</Icode>
</Medicine>
</Disease>
</Patient>
<Patient>
<Fname>Jayne</Fname>
<Lname>Joyce</Lname>
<Record>F00156</Record>
<Disease>
<Date>3/18/2009</Date>
<Dcode>D3266</Dcode>
<Comm></Comm>
<Medicine>
<Mcode>M00006</Mcode>
<Qnt>1</Qnt>
<Unit>m</Unit>
<Icode>
<Num>803125</Num>
</Icode>
</Medicine>
</Disease>
</Patient>
</root>
产生了想要的正确结果:
<root>
<Patient>
<Patient_PK>1</Patient_PK>
<Fname>John</Fname>
<Lname>Doe</Lname>
<Record>F00025</Record>
<Disease>
<Disease_PK>1</Disease_PK>
<Patient_FK>1</Patient_FK>
<Date>3/3/2009</Date>
<Dcode>D0456</Dcode>
<Comm>comment</Comm>
<Medicine>
<Medicine_PK>1</Medicine_PK>
<Disease_FK>1</Disease_FK>
<Mcode>M00025</Mcode>
<Qnt>0.01</Qnt>
<Unit>l</Unit>
</Medicine>
</Disease>
<Disease>
<Disease_PK>2</Disease_PK>
<Patient_FK>1</Patient_FK>
<Date>3/15/2009</Date>
<Dcode>D4415</Dcode>
<Comm/>
</Disease>
<Disease>
<Disease_PK>3</Disease_PK>
<Patient_FK>1</Patient_FK>
<Date>3/19/2009</Date>
<Dcode>D0176</Dcode>
<Comm/>
<Medicine>
<Medicine_PK>2</Medicine_PK>
<Disease_FK>3</Disease_FK>
<Mcode>M00015</Mcode>
<Qnt>10</Qnt>
<Unit>ml</Unit>
</Medicine>
<Medicine>
<Medicine_PK>3</Medicine_PK>
<Disease_FK>3</Disease_FK>
<Mcode>M00006</Mcode>
<Qnt>1</Qnt>
<Unit>m</Unit>
<Icode>
<Num>803125</Num>
<Num>803005</Num>
</Icode>
</Medicine>
</Disease>
</Patient>
<Patient>
<Patient_PK>2</Patient_PK>
<Fname>Jayne</Fname>
<Lname>Joyce</Lname>
<Record>F00156</Record>
<Disease>
<Disease_PK>4</Disease_PK>
<Patient_FK>2</Patient_FK>
<Date>3/18/2009</Date>
<Dcode>D3266</Dcode>
<Comm/>
<Medicine>
<Medicine_PK>3</Medicine_PK>
<Disease_FK>4</Disease_FK>
<Mcode>M00006</Mcode>
<Qnt>1</Qnt>
<Unit>m</Unit>
<Icode>
<Num>803125</Num>
</Icode>
</Medicine>
</Disease>
</Patient>
</root>