Upfront,我对Access感到很自在,我得到了XML的一般概念,但我是XSLT的新手,所以如果我的解释/术语表达不好,请原谅我的帖子。
我有一个XML源文件,我必须将其导入Access数据库并链接所有grandparent/parent/child/child/...
关系以进行报告。我已经在这里阅读了类似的帖子(非常感谢之前发布的所有努力)并拼凑了一个XSLT文件,以创建所有创建的表之间的链接(学校链接到学生< / em>使用[unique] SchoolNumber 字段,学生使用[唯一] SID 字段链接其中的各个孩子。
但是,我很难过如何让Name节点数据在各自的表中正确对齐。在XML文件中,Name属性用于Student节点和Guardian节点,因此它创建一个Name表并将Student和Guardian Name字段放在一个Name表中。 Name表应该只包含 Student 名称( First,Middle,Last ),Guardian表应该包含 Guardian名称( First,Last )以及其他 Guardian 字段( Relationship,Phone,[PhoneType )。
此外,在XML中,Guardian Phone属性包含一个嵌套元素type="HOME"
,该元素应包含在生成的Guardian表中。源XML(我无法控制它)如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns1:SchoolUpload xmlns:ns1="http://ontario.ca">
<ns1:School>
<ns1:SchoolNumber>123456789</ns1:SchoolNumber>
<ns1:Students>
<ns1:Student>
<ns1:SID>10101010</ns1:SID>
<ns1:Name>
<ns1:First>Student1</ns1:First>
<ns1:Middle>Middle</ns1:Middle>
<ns1:Last>Surname</ns1:Last>
</ns1:Name>
<ns1:AliasName>
<ns1:First>Red</ns1:First>
<ns1:Last>Blue</ns1:Last>
</ns1:AliasName/>
<ns1:Gender>M</ns1:Gender>
<ns1:BirthDate>1991-10-29</ns1:BirthDate>
<ns1:Language>en</ns1:Language>
<ns1:Guardian>
<ns1:Name>
<ns1:First>Primary</ns1:First>
<ns1:Last>Guardian</ns1:Last>
</ns1:Name>
<ns1:Relationship>MOTHER</ns1:Relationship>
<ns1:Phone type="HOME">111-111-1111</ns1:Phone>
</ns1:Guardian>
<ns1:Guardian>
<ns1:Name>
<ns1:First>Secondary</ns1:First>
<ns1:Last>Guardian</ns1:Last>
</ns1:Name>
<ns1:Relationship>FATHER</ns1:Relationship>
<ns1:Phone type="HOME">222-222-2222</ns1:Phone>
</ns1:Guardian>
<ns1:Address>
<ns1:StreetAddress>15 Main Street</ns1:StreetAddress>
<ns1:City>Guelph</ns1:City>
<ns1:Province>ON</ns1:Province>
<ns1:PostalCode>N5N5N5</ns1:PostalCode>
</ns1:Address>
<ns1:Phone type="HOME">333-333-3333</ns1:Phone>
</ns1:Student>
</ns1:Students>
</ns1:School>
</ns1:SchoolUpload>
我拼凑的XSLT文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ns1="http://ontario.ca" exclude-result-prefixes="ns1">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns1:Student">
<xsl:copy>
<xsl:copy-of select="ancestor::ns1:School/ns1:SchoolNumber"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns1:Student/ns1:Name">
<xsl:copy>
<xsl:copy-of select="ancestor::ns1:Student/ns1:SID"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns1:AliasName|ns1:Guardian|ns1:Address">
<xsl:copy>
<xsl:copy-of select="ancestor::ns1:Student/ns1:SID"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
使用XSLT文件将XML导入Access会导致Access创建6个表( School,Student,Name,Guardian,Address,AliasName ),所有这些表都可以链接。但是,我不知道如何实现我想要实现的最终结果。在此之前,我非常感谢可以提供的任何反馈。
答案 0 :(得分:2)
考虑展平嵌套的名称和 AliasName 节点,使其直接将子项呈现给学生和 Guardian 。您可以使用<xsl:apply-templates>
但没有<xsl:copy>
的模板执行此操作。并且因为它们共享相同的元素名称,所以使用两个不同的模板,其中 AliasName的新子项将父别名连接到 AliasNameFirst 和<的元素名称EM> AliasNameLast
由于MS Access的XML方法以元素为中心并忽略了属性,因此请考虑将属性迁移到元素。由于 @type 不止一次出现,请使用xsl:call-template
以避免重复。使用以下调整后的XSLT,只能导入四个表:学校,学生,监护人和地址。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:ns1="http://ontario.ca" exclude-result-prefixes="ns1">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns1:Student">
<xsl:copy>
<xsl:copy-of select="ancestor::ns1:School/ns1:SchoolNumber"/>
<xsl:apply-templates/>
<xsl:call-template name="phonetype"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns1:Name">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="ns1:AliasName">
<xsl:variable select="local-name()" name="parent_name"/>
<xsl:for-each select="*">
<xsl:element name="ns1:{concat($parent_name, local-name())}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</xsl:template>
<xsl:template match="ns1:Guardian|ns1:Address">
<xsl:copy>
<xsl:copy-of select="ancestor::ns1:Student/ns1:SID"/>
<xsl:apply-templates/>
<xsl:call-template name="phonetype"/>
</xsl:copy>
</xsl:template>
<xsl:template name="phonetype">
<xsl:if test="ns1:Phone/@type">
<ns1:Phonetype><xsl:value-of select="ns1:Phone/@type"/></ns1:Phonetype>
</xsl:if>
</xsl:template>
</xsl:stylesheet>