将XML文件导入Access并创建祖父母/父/子关系

时间:2017-03-10 22:34:13

标签: xml ms-access xslt import

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 ),所有这些表都可以链接。但是,我不知道如何实现我想要实现的最终结果。在此之前,我非常感谢可以提供的任何反馈。

1 个答案:

答案 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>