【问题标题】:XSLT 1.0 multiple keys cross referencing and consolidatingXSLT 1.0 多键交叉引用和合并
【发布时间】:2015-10-27 04:49:30
【问题描述】:

感谢您花时间查看我的问题。

我有一个输入结构(如下),其中每一行代表从一个位置项到另一个位置项的移动。所以每一行都有一个从位置和一个到位置。

目标是一个嵌套的 xml,其中位置对象具有一些标题和项目级别信息。我需要在所有行中选择 distint from 和 to 位置并映射它们的项目级别详细信息。

输入和所需转换输出的示例。

我有一个平面数据库提取 xml,看起来像

<Data>
<row>
    <Movement>Home to Work</Movement>
    <COMP_ID_F>HID001</COMP_ID_F>
    <ITEM_ID_F>1</ITEM_ID_F>
    <FIELDS_F> More home related data  </FIELDS_F>
    <COMP_ID_T>WID001</COMP_ID_T>
    <ITEM_ID_T>2</ITEM_ID_T>
    <FIELDS_T> More work related data</FIELDS_T>
</row>
<row>
    <Movement>Home to Work</Movement>
    <COMP_ID_F>HID001</COMP_ID_F>
    <ITEM_ID_F>1</ITEM_ID_F>
    <FIELDS_F> More home related data  </FIELDS_F>
    <COMP_ID_T>WID001</COMP_ID_T>
    <ITEM_ID_T>2</ITEM_ID_T>
    <FIELDS_T> More work related data</FIELDS_T>
</row>
<row>
    <Movement>Home to Work</Movement>
    <COMP_ID_F>HID001</COMP_ID_F>
    <ITEM_ID_F>1</ITEM_ID_F>
    <FIELDS_F> More home related data  </FIELDS_F>
    <COMP_ID_T>WID001</COMP_ID_T>
    <ITEM_ID_T>3</ITEM_ID_T>
    <FIELDS_T> More work related data</FIELDS_T>
</row>
<row>
    <Movement>Home to Work</Movement>
    <COMP_ID_F>HID001</COMP_ID_F>
    <ITEM_ID_F>2</ITEM_ID_F>
    <FIELDS_F> More home related data  </FIELDS_F>
    <COMP_ID_T>WID001</COMP_ID_T>
    <ITEM_ID_T>4</ITEM_ID_T>
    <FIELDS_T> More work related data</FIELDS_T>
</row>
<row>
    <Movement>Home to Work</Movement>
    <COMP_ID_F>HID002</COMP_ID_F>
    <ITEM_ID_F>1</ITEM_ID_F>
    <FIELDS_F> More home related data  </FIELDS_F>
    <COMP_ID_T>WID001</COMP_ID_T>
    <ITEM_ID_T>5</ITEM_ID_T>
    <FIELDS_T> More work related data</FIELDS_T>
</row>
<row>
    <Movement>Home to Work</Movement>
    <COMP_ID_F>HID002</COMP_ID_F>
    <ITEM_ID_F>2</ITEM_ID_F>
    <FIELDS_F> More home related data  </FIELDS_F>
    <COMP_ID_T>WID002</COMP_ID_T>
    <ITEM_ID_T>1</ITEM_ID_T>
    <FIELDS_T> More work related data</FIELDS_T>
</row>
</Data>

转换后的输出需要是

 <Target>
<Events>
    <Movement>Home to Work</Movement>
    <Movement>Home to Work</Movement>
    <Movement>Home to Work</Movement>
    <Movement>Home to Work</Movement>
    <Movement>Home to Work</Movement>
    <Movement>Home to Work</Movement>
</Events>
<Locations>
    <Home>
        <id>HID001</id>
        <item>
            <id>1</id>
        </item>
        <item>
            <id>2</id>
        </item>
    </Home> 
    <Home>
        <id>HID002</id>
        <item>
            <id>1</id>
        </item>
        <item>
            <id>2</id>
        </item>
    </Home> 
    <Work>
        <id>WID001</id>
        <item>
            <id>1</id>
        </item>
        <item>
            <id>2</id>
        </item>
        <item>
            <id>3</id>
        </item>
        <item>
            <id>4</id>
        </item>
        <item>
            <id>5</id>
        </item>
    </Work>
    <Work>
        <id>WID002</id>
        <item>
            <id>1</id>
        </item>
    </Work>
</Locations>
</Target>

现在我已经尝试了许多使用 Keys 和生成 id 的选项。所以请看一下并指出我哪里出错了。或者如果有更好的方法来实现这个输出。

我创建了 4 个键

<xsl:key name="fcreg" match="row" use="COMP_ID_F"/>
<xsl:key name="fcireg" match="row" use="ITEM_ID_F"/>
<xsl:key name="tcreg" match="row" use="COMP_ID_T"/>
<xsl:key name="tcireg" match="row" use="ITEM_ID_T"/>

我的 XSLT 执行以下逻辑

<Target>
<!--transform all events-->
<Events>
    <xsl:for-each select="Data/row">
        <!-- get movement-->
    </xsl:for-each>
</Events>

<!--transform all from locations-->
<xsl:for-each select="Data/row[generate-id() = generate-id(key('fcreg',COMP_ID_F)[1])]">
    <xsl:for-each select="key('fcreg',COMP_ID_F)[generate-id() = generate-id(key('fcireg', ITEM_ID_F)[COMP_ID_F=current()/COMP_ID_F][1])]">
        <xsl:variable name="items" select="key('fcreg', COMP_ID_F)[ITEM_ID_F = current()/ITEM_ID_F]"/>
        <home>
            <xsl:value-of select="COMP_ID_F"/>
            <xsl:for-each select="$items">
                <item>
                    <id>
                        <xsl:value-of select="ITEM_ID_F"/>
                    </id>
                </item>
            </xsl:for-each>
        </home>
    </xsl:for-each>
</xsl:for-each>


<!--transform all to locations-->
<xsl:for-each select="Data/row[generate-id() = generate-id(key('tcreg',COMP_ID_T)[1])]">
    <xsl:for-each select="key('tcreg',COMP_ID_T)[generate-id() = generate-id(key('tcireg', ITEM_ID_T)[COMP_ID_T=current()/COMP_ID_T][1])]">
        <xsl:variable name="items" select="key('tcreg', COMP_ID_T)[ITEM_ID_T = current()/ITEM_ID_T]"/>
        <work>
            <xsl:value-of select="COMP_ID_T"/>
            <xsl:for-each select="$items">
                <item>
                    <id>
                        <xsl:value-of select="ITEM_ID_T"/>
                    </id>
                </item>
            </xsl:for-each>
        </work>
    </xsl:for-each>
</xsl:for-each>
</Target>

我哪里错了?非常感谢任何帮助。

提前致谢。

【问题讨论】:

  • 这令人困惑。请用文字说明所需的逻辑。
  • 谢谢迈克尔,我已经围绕所需的逻辑写了一些话。

标签: xml xslt xslt-1.0 xslkey


【解决方案1】:

您似乎正在尝试获取不同的 COMP_ID_F 元素,然后对于每个不同的值,您想要列出与其关联的所有不同的 ITEM_ID_F

您的fcreg 键没问题,但是因为ITEM_ID_F 项取决于COMP_ID_F 的值,所以您需要fcireg 的串联键

<xsl:key name="fcireg" match="row" use="concat(COMP_ID_F, '|', ITEM_ID_F)"/>

所以,您首先像以前一样选择ITEM_ID_F...

<xsl:for-each select="Data/row[generate-id() = generate-id(key('fcreg',COMP_ID_F)[1])]">

但在此范围内,您可以为当前 COMP_ID_F 元素选择不同的 ITEM_ID_F 项目。这样做是这样的:

<xsl:for-each select="Data/row[generate-id() = generate-id(key('fcreg',COMP_ID_F)[1])]">
    <home>
        <id><xsl:value-of select="COMP_ID_F" /></id>
        <xsl:for-each select="key('fcreg',COMP_ID_F)[generate-id() = generate-id(key('fcireg',concat(COMP_ID_F, '|', ITEM_ID_F))[1])]">
            <item>
                <id>
                    <xsl:value-of select="ITEM_ID_F"/>
                </id>
            </item>
        </xsl:for-each>
    </home>
</xsl:for-each>

你会有一个类似的“T”元素

试试这个 XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />

    <xsl:key name="fcreg" match="row" use="COMP_ID_F"/>
    <xsl:key name="fcireg" match="row" use="concat(COMP_ID_F, '|', ITEM_ID_F)"/>
    <xsl:key name="tcreg" match="row" use="COMP_ID_T"/>
    <xsl:key name="tcireg" match="row" use="concat(COMP_ID_T, '|', ITEM_ID_T)"/>

    <xsl:template match="/">
        <Target>
            <Events>
                <xsl:copy-of select="Data/row/Movement" />
            </Events>

        <xsl:for-each select="Data/row[generate-id() = generate-id(key('fcreg',COMP_ID_F)[1])]">
            <Home>
                <id><xsl:value-of select="COMP_ID_F" /></id>
                <xsl:for-each select="key('fcreg',COMP_ID_F)[generate-id() = generate-id(key('fcireg',concat(COMP_ID_F, '|', ITEM_ID_F))[1])]">
                    <item>
                        <id>
                            <xsl:value-of select="ITEM_ID_F"/>
                        </id>
                    </item>
                </xsl:for-each>
            </Home>
        </xsl:for-each>

        <xsl:for-each select="Data/row[generate-id() = generate-id(key('tcreg',COMP_ID_T)[1])]">
            <Work>
                <id><xsl:value-of select="COMP_ID_T" /></id>
                <xsl:for-each select="key('tcreg',COMP_ID_T)[generate-id() = generate-id(key('tcireg',concat(COMP_ID_T, '|', ITEM_ID_T))[1])]">
                    <item>
                        <id>
                            <xsl:value-of select="ITEM_ID_T"/>
                        </id>
                    </item>
                </xsl:for-each>
            </Work>
        </xsl:for-each>
        </Target>
    </xsl:template>
</xsl:stylesheet>

【讨论】:

  • 这正是我想要的。非常感谢您抽出宝贵时间进行解释。我认为查看您的第二个 for-each 条件,我现在对键的工作方式有了更好的了解。 :)
猜你喜欢
  • 2016-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多