XSLT 1.0 多键交叉引用和合并
XSLT 1.0 multiple keys cross referencing and consolidating
感谢您抽出时间来看我的问题。
我有一个输入结构(如下),其中每一行代表从一个位置项到另一个位置项的移动。所以每一行都有一个起始位置和一个终止位置。
目标是嵌套的 xml,其中位置 object 具有一些 header 和项目级别信息。我需要在所有行中选择不同的位置,并映射它们的项目级别详细信息。
输入示例和所需的转换输出。
我有一个平面数据库提取物 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>
现在,我已经尝试了多种使用密钥并生成 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>
我哪里错了?非常感谢任何帮助。
提前致谢。
看起来您正在尝试获取不同的 COMP_ID_F
元素,然后对于每个不同的值,您想要列出与其关联的所有不同的 ITEM_ID_F
。
您的 fcreg
键没问题,但是因为 ITEM_ID_F
项取决于 COMP_ID_F
的值,您需要 fcireg
[=23= 的串联键]
<xsl:key name="fcireg" match="row" use="concat(COMP_ID_F, '|', ITEM_ID_F)"/>
所以,您像以前一样从 selecting ITEM_ID_F
开始...
<xsl:for-each select="Data/row[generate-id() = generate-id(key('fcreg',COMP_ID_F)[1])]">
但在此范围内,您然后 select 当前 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>
感谢您抽出时间来看我的问题。
我有一个输入结构(如下),其中每一行代表从一个位置项到另一个位置项的移动。所以每一行都有一个起始位置和一个终止位置。
目标是嵌套的 xml,其中位置 object 具有一些 header 和项目级别信息。我需要在所有行中选择不同的位置,并映射它们的项目级别详细信息。
输入示例和所需的转换输出。
我有一个平面数据库提取物 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>
现在,我已经尝试了多种使用密钥并生成 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>
我哪里错了?非常感谢任何帮助。
提前致谢。
看起来您正在尝试获取不同的 COMP_ID_F
元素,然后对于每个不同的值,您想要列出与其关联的所有不同的 ITEM_ID_F
。
您的 fcreg
键没问题,但是因为 ITEM_ID_F
项取决于 COMP_ID_F
的值,您需要 fcireg
[=23= 的串联键]
<xsl:key name="fcireg" match="row" use="concat(COMP_ID_F, '|', ITEM_ID_F)"/>
所以,您像以前一样从 selecting ITEM_ID_F
开始...
<xsl:for-each select="Data/row[generate-id() = generate-id(key('fcreg',COMP_ID_F)[1])]">
但在此范围内,您然后 select 当前 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>