恢复包含在多个文件中的相对链

Restoring relative chain contained in multiple files

本题是上一题的逻辑延续(形式上,只是元素的名字变了,这里,结构上,一切都保持不变)。新条件是现在添加了两个额外的层次结构级别。每个新级别都在单独的 xml 文件中表示。总体目标保持不变:恢复一个文件中从最低元素到最高元素的整个层次结构链。源数据包含在以下文件中:

我 - base.xml - 解决了过去的部分。在一个文件中恢复层次结构已在较早的 中得到解决。层级模型为parent --> subparent --> child(这里用region --> city --> street表示)。

可视化方案 base.xml here

base.xml 的解决方案代码:

1 个来源:

<document ID-1="regionID"   ID-2="NULL"  ID-3="value" attr-4="region"/>      <!-- this is parent's node -->
<document ID-1="cityID" ID-2="regionID" ID-3="value" attr-4="city" />       <!-- this is subparent -->

<document ID-1="aaa" ID-2="cityID" ID-3="value" attr-4="street-1"/>     <!-- child-1 -->
<document ID-1="bbb" ID-2="cityID" ID-3="value" attr-4="street-2"/>     <!-- child-2 -->
<document ID-1="ccc" ID-2="cityID" ID-3="value" attr-4="street-3"/>     <!-- child-3 -->
<document ID-1="ddd" ID-2="cityID" ID-3="value" attr-4="street-4"/>     <!-- child-4 -->

2-xslt-solution

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>

<xsl:key name="ref" match="document" use="@ID-1"/>

<xsl:template match="document">
    <xsl:copy>
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates select="key('ref', @ID-2)" mode="att"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="document" mode="att">
    <xsl:param name="pos" select="count(@*) + 1"/>
    <xsl:attribute name="attr-{$pos}">
        <xsl:value-of select="@attr-4"/>
    </xsl:attribute>
    <xsl:apply-templates select="key('ref', @ID-2)" mode="att">
        <xsl:with-param name="pos" select="$pos + 1"/>
    </xsl:apply-templates>
</xsl:template>

</xsl:stylesheet>

3-输出

<document ID-1="regionID"   ID-2="NULL"  ID-3="value" attr-4="region"/>                <!-- this is parent's date -->
<document ID-1="cityID" ID-2="regionID" ID-3="value" attr-4="city" attr-5="region"/>   <!-- this is subparent -->

<document ID-1="aaa" ID-2="cityID" ID-3="value" attr-4="street-1"  attr-5="city" attr-6="region" />  <!-- child-1 -->
<document ID-1="bbb" ID-2="cityID" ID-3="value" attr-4="street-2"  attr-5="city" attr-6="region" />  <!-- child-2 -->
<document ID-1="ccc" ID-2="cityID" ID-3="value" attr-4="street-3"  attr-5="city" attr-6="region" />  <!-- child-3 -->
<document ID-1="ddd" ID-2="cityID" ID-3="value" attr-4="street-4"  attr-5="city" attr-6="region" />  <!-- child-4 -->

II - houses.xml 全新的可视化方案 here

元素“house”具有互连属性“ID-1”。它将 houses.xml 与 base.xml 联系起来 以下规则适用于此属性:“每个来自 houses.xml 的 ID-1 都与 base.xml ID-1(街道级别)有联系。但并非来自 base.xml 的每个 ID-1 都与来自 houses.xml 的 ID-1 相关(未连接城市和地区级别)。

一些想法:在base.xml示例中恢复运动从较高级别变为较低级别。在这种情况下,我可以假设一个变体以相反的方式进行计算——从低到高。因此提醒一下,直接跟随 ID-1 的行可能不会匹配和恢复所有节点(城市和地区)可能会很有用。

III - rooms.xml - 最低级文件

所以,所有的源代码都是:

base.xml

<document ID-1="regionID"   ID-2="NULL"  ID-3="value" attr-4="region"/>      <!-- this is parent's node -->
<document ID-1="cityID" ID-2="regionID" ID-3="value" attr-4="city" />       <!-- this is subparent -->

<document ID-1="aaa" ID-2="cityID" ID-3="value" attr-4="street-1"/>     <!-- child-1 -->
<document ID-1="bbb" ID-2="cityID" ID-3="value" attr-4="street-2"/>     <!-- child-2 -->
<document ID-1="ccc" ID-2="cityID" ID-3="value" attr-4="street-3"/>     <!-- child-3 -->
<document ID-1="ddd" ID-2="cityID" ID-3="value" attr-4="street-4"/>     <!-- child-4 -->

houses.xml

<houses>
    <house ID-1="aaa" HOUSE-ID="zzzz" housenum="17" buildnum="a"/>
    <house ID-1="bbb" HOUSE-ID="yyyy" housenum="18" buildnum="NULL"/>
    <house ID-1="ccc" HOUSE-ID="xxxx" housenum="19" buildnum="NULL"/>
    <house ID-1="ddd" HOUSE-ID="wwww" housenum="20" buildnum="NULL"/>
</houses>

rooms.xml

<rooms>
    <room ROOM-ID="value" HOUSE-ID="zzzz" roomnum="123" roomtype="value"/>
    <room ROOM-ID="value" HOUSE-ID="yyyy" roomnum="345" roomtype="value"/>
    <room ROOM-ID="value" HOUSE-ID="xxxx" roomnum="567" roomtype="value"/>
    <room ROOM-ID="value" HOUSE-ID="wwww" roomnum="789" roomtype="value"/>
</rooms>

近似输出。 这里假定输出表示为新的 .xml 文件,但它可以基于例如 rooms.xml 。在特定的解决方案中,它可能会有所不同,完整 parental 链的复制原则很重要。交叉命名的互连属性(HOUSE-ID,ID-1 可能来自不同的路径,具体取决于 soution 的确切表达式。不知何故它们必须保留。

<Restored-Objects>
    <object ROOM-ID="value" HOUSE-ID="zzzz" roomnum="123" roomtype="value"                  <!--room  attrributes -->
            ID-1="aaa" housenum="17" buildnum="a"                                           <!--house attrributes -->
            ID-2="cityID" ID-3="value" attr-4="street-1"  attr-5="city" attr-6="region"     <!--base  attrributes -->
    />
    <object ROOM-ID="value" HOUSE-ID="yyyy" roomnum="345" roomtype="value"
            ID-1="bbb" housenum="18" buildnum="NULL"
            ID-2="cityID" ID-3="value" attr-4="street-2"  attr-5="city" attr-6="region" 
    />
    <object ROOM-ID="value" HOUSE-ID="xxxx" roomnum="567" roomtype="value"
            ID-1="ccc" housenum="19" buildnum="NULL"    
            ID-2="cityID" ID-3="value" attr-4="street-3"  attr-5="city" attr-6="region"
    />
    <object ROOM-ID="value" HOUSE-ID="wwww" roomnum="789" roomtype="value" 
            ID-1="ddd" housenum="20" buildnum="NULL"
            ID-2="cityID" ID-3="value" attr-4="street-4"  attr-5="city" attr-6="region"
    />      
    <object ID-1="regionID"   ID-2="NULL"  ID-3="value" attr-4="region"/>                <!-- this is parent's date -->
    <object ID-1="cityID" ID-2="regionID" ID-3="value" attr-4="city" attr-5="region"/>   <!-- this is subparent -->
</Restored-Objects>

我欢迎从 XSLT 1.0 到 3.0 的任何解决方案。第三个版本也很有趣,因为文件大小。如果不切割,它们会很大。所以流媒体版本可以派上用场。

为了轻松地对多个文档使用键,key 函数的 XSLT 2/3 重载将文档或一般子树根节点作为其第三个参数派上用场。

使用它我认为你可以很容易地在 room 元素上构造属性转换为 object 元素:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:param name="base-doc" select="doc('base.xml')"/>

  <xsl:param name="houses-doc" select="doc('houses.xml')"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:key name="house-ref" match="house" use="@HOUSE-ID"/>

  <xsl:key name="doc-ref" match="document" use="@ID-1"/>

  <xsl:template match="room">
      <object>
          <xsl:variable 
            name="house-ref" select="key('house-ref', @HOUSE-ID, $houses-doc)"/>
          <xsl:variable 
            name="doc-ref"
            select="key('doc-ref', $house-ref/@ID-1, $base-doc)"/>
          <xsl:variable
            name="atts" 
            select="@*, $house-ref!(@* except @HOUSE-ID), $doc-ref!(@* except (@ID-1, @attr-4))"/>
          <xsl:copy-of select="$atts"/>
          <xsl:apply-templates select="$doc-ref" mode="att">
              <xsl:with-param name="pos" select="3 + 1"/>
          </xsl:apply-templates>
      </object>
  </xsl:template>

  <xsl:template match="document" mode="att">
        <xsl:param name="pos"/>
        <xsl:attribute name="attr-{$pos}">
            <xsl:value-of select="@attr-4"/>
        </xsl:attribute>
        <xsl:apply-templates select="key('doc-ref', @ID-2)" mode="att">
            <xsl:with-param name="pos" select="$pos + 1"/>
        </xsl:apply-templates>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/bFWRAoL/1(内联其他文档以确保示例的完整性)给出

<rooms>
    <object ROOM-ID="value" HOUSE-ID="zzzz" roomnum="123" roomtype="value" ID-1="aaa" housenum="17" buildnum="a" ID-2="cityID" ID-3="value" attr-4="street-1" attr-5="city" attr-6="region"/>
    <object ROOM-ID="value" HOUSE-ID="yyyy" roomnum="345" roomtype="value" ID-1="bbb" housenum="18" buildnum="NULL" ID-2="cityID" ID-3="value" attr-4="street-2" attr-5="city" attr-6="region"/>
    <object ROOM-ID="value" HOUSE-ID="xxxx" roomnum="567" roomtype="value" ID-1="ccc" housenum="19" buildnum="NULL" ID-2="cityID" ID-3="value" attr-4="street-3" attr-5="city" attr-6="region"/>
    <object ROOM-ID="value" HOUSE-ID="wwww" roomnum="789" roomtype="value" ID-1="ddd" housenum="20" buildnum="NULL" ID-2="cityID" ID-3="value" attr-4="street-4" attr-5="city" attr-6="region"/>
</rooms>

我还没有从辅助文档中了解哪些元素需要copied/transformed。