【问题标题】:Import XML file into Access and create grandparent/parent/child relationships将 XML 文件导入 Access 并创建祖父母/父母/孩子关系
【发布时间】:2017-03-10 22:34:12
【问题描述】:

首先,我对 Access 很熟悉,并且了解了 XML 的一般概念,但我是 XSLT 的新手,所以如果我的解释/术语表达不佳,请原谅我的帖子。

我有一个 XML 源文件,我必须将其导入 Access 数据库并链接所有 grandparent/parent/child/child/... 关系以用于报告目的。我在这里阅读了类似的帖子(非常感谢之前发布的所有努力)并拼凑了一个 XSLT 文件以在所有创建的表之间创建链接(学校链接到学生 使用 [unique] SchoolNumber 字段,Student 使用 [unique] SID 字段链接它的各个孩子。

但是,我不知道如何让名称节点数据在各自的表中正确对齐。在 XML 文件中,Name 属性同时用于 Student 节点和 Guardian 节点,因此它会创建一个 Name 表并将 Student 和 Guardian Name 字段放在一个 Name 表中。 Name 表应仅包含 Student 名(First、Middle、Last),而 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),所有这些表都可以链接。但是,我不知道如何达到我想要达到的最终结果。在此之前,我非常感谢您提供的任何反馈。

【问题讨论】:

    标签: xml ms-access xslt import


    【解决方案1】:

    考虑展平嵌套的 NameAliasName 节点,以将它们直接呈现给 StudentGuardian 的子节点。你可以通过一个只有&lt;xsl:apply-templates&gt; 的模板来做到这一点,没有&lt;xsl:copy&gt;。由于它们共享相同的元素名称,因此使用了两个不同的模板,其中 AliasName 的 新子级将父级 Alias 连接到 AliasNameFirst 和 AliasNameLast.

    由于 MS Access 的 XML 方法以元素为中心并忽略属性,因此请考虑将属性迁移到元素。由于 @type 不止一次出现,因此请使用 xsl:call-template 来避免重复。使用以下调整后的 XSLT,应该只导入四个表:School、Student、Guardian 和 Address。

    <?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>
    

    【讨论】:

    • 嗨冻糕。首先,感谢您的时间和反馈(非常感谢)。我知道您使用“phonetype”方法/调用将该属性转换/添加到 Student 和 Guardian 节点所做的事情(非常酷)。我注意到“扁平化” Name 和 AliasName 字段的效果是分别用 Alias.First 和 Alias.Last 覆盖 Student.First 和 Student.Last 属性的值。 Student.Middle 值不受影响(我假设),因为没有 Guardian.Middle 属性。待定...
    • 我“展开”了 AliasName 节点并将 Student.SID 值复制到 AliasName 节点,该节点创建了 AliasName 表,并通过 SID 属性链接到 Student 表。这是一个可行的解决方案,但是,我很想知道是否有办法展平 AliasName 字段(根据您的解决方案)并将其 First 和 Last 子属性重命名为其他内容,例如 AliasFirst 和 AliasLast?最终结果是 Student 表将包含 First、Middle、Last、AliasFirst 和 AliasLast 字段。
    • 查看更新的 XSLT 脚本。我没有想到 NameAliasName 共享相同的子名称。
    • 老实说,我边做边学!对我来说最好的教程是深入研究一个问题并使用有问题的 StackOverflow 帖子。对于 VBA(所有 MS Office 应用程序),请读入 MSXML 库以进行所有 XML 处理。像数据库/电子表格这样的表格数据是二维的(逐列),只有一种格式类型的 XML 可以有各种嵌套。 XSLT 有助于迁移。
    • 顺便说一下,为以后的读者保留这一点。事实上,如果回答有帮助,请点击旁边的勾号接受回答并确认解决方案。
    猜你喜欢
    • 2011-01-12
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多