使用xslt连接来自不同xpath的数据
我正在尝试使用XSLT进行xml转换。我有以下xml:使用xslt连接来自不同xpath的数据,xslt,Xslt,我正在尝试使用XSLT进行xml转换。我有以下xml: <myxml> <dataType1> <value1> A1 </value1> <value2> A2 </value2> </dataType1> <dataType1> <value1> B1 </value1>
<myxml>
<dataType1>
<value1>
A1
</value1>
<value2>
A2
</value2>
</dataType1>
<dataType1>
<value1>
B1
</value1>
<value2>
B2
</value2>
</dataType1>
<dataType2>
<value1>
A1
</value1>
<value3>
A3
</value3>
</dataType2>
<dataType2>
<value1>
B1
</value1>
<value3>
B3
</value3>
</dataType2>
A1
A2
地下一层
地下二层
A1
A3
地下一层
地下三层
每个datatype2都有一个元素value1,它是datatype2中的外键,因此我必须基于value1映射此数据
如果存在一个值为1=A1的dataType1和一个值为1=A1的dataType2,那么我必须创建一个值为value2和value3的xml,因此结果如下:
<resultxml>
<data>
<value2>
A2
</value2>
<value3>
A3
</value3>
</data>
<data>
<value2>
B2
</value2>
<value3>
B3
</value3>
</data>
A2
A3
地下二层
地下三层
我想在读取dataType1时动态创建变量,然后在读取datatype2时调用它们,但当我在某个论坛上阅读时,这是不可能的,所以我的问题是:是否可以按照我解释的那样做?如果是,我必须遵循哪种方法(欢迎举例)
提前感谢这里是XSLT 2.0样式表:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:key name="k1" match="dataType2" use="normalize-space(value1)"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="dataType1[key('k1', value1)]">
<data>
<xsl:apply-templates select="node() except value1, key('k1', normalize-space(value1))/*[not(self::value1)]"/>
</data>
</xsl:template>
<xsl:template match="dataType1[not(key('k1', normalize-space(value1)))] | dataType2"/>
</xsl:stylesheet>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:key name="k1" match="dataType2" use="normalize-space(value1)"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="dataType1">
<xsl:variable name="refs" select="key('k1', normalize-space(value1))"/>
<xsl:if test="$refs">
<data>
<xsl:apply-templates select="node()[not(self::value1)] | $refs/*[not(self::value1)]"/>
</data>
</xsl:if>
</xsl:template>
<xsl:template match="dataType2"/>
</xsl:stylesheet>
当上述样式表应用于输入时
<myxml>
<dataType1>
<value1>
A1
</value1>
<value2>
A2
</value2>
</dataType1>
<dataType1>
<value1>
B1
</value1>
<value2>
B2
</value2>
</dataType1>
<dataType2>
<value1>
A1
</value1>
<value3>
A3
</value3>
</dataType2>
<dataType2>
<value1>
B1
</value1>
<value3>
B3
</value3>
</dataType2>
</myxml>
A1
A2
地下一层
地下二层
A1
A3
地下一层
地下三层
使用Saxon 9.4,结果是
<?xml version="1.0" encoding="UTF-8"?><myxml>
<dataType1>
<value1>
A1
</value1>
<value2>
A2
</value2>
</dataType1>
<dataType1>
<value1>
B1
</value1>
<value2>
B2
</value2>
</dataType1>
</myxml>
A1
A2
地下一层
地下二层
使用XSLT1.0,您不能在匹配模式中使用键,因此需要更多的代码,稍后我将添加一个示例
[编辑]
以下是XSLT 1.0样式表:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:key name="k1" match="dataType2" use="normalize-space(value1)"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="dataType1[key('k1', value1)]">
<data>
<xsl:apply-templates select="node() except value1, key('k1', normalize-space(value1))/*[not(self::value1)]"/>
</data>
</xsl:template>
<xsl:template match="dataType1[not(key('k1', normalize-space(value1)))] | dataType2"/>
</xsl:stylesheet>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:key name="k1" match="dataType2" use="normalize-space(value1)"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="dataType1">
<xsl:variable name="refs" select="key('k1', normalize-space(value1))"/>
<xsl:if test="$refs">
<data>
<xsl:apply-templates select="node()[not(self::value1)] | $refs/*[not(self::value1)]"/>
</data>
</xsl:if>
</xsl:template>
<xsl:template match="dataType2"/>
</xsl:stylesheet>
我的提案
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" encoding="UTF-8" indent="no" />
<xsl:template match="/">
<resultxml>
<xsl:for-each select="/myxml/dataType1">
<xsl:variable name="fk" select="value1" />
<data>
<xsl:copy-of select="value2" />
<xsl:copy-of select="/myxml/dataType2[value1 = $fk]/value3" />
</data>
</xsl:for-each>
</resultxml>
</xsl:template>
</xsl:stylesheet>
此转换:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kType1" match="dataType1" use="normalize-space(value1)"/>
<xsl:template match="dataType2[key('kType1', normalize-space(value1))]">
<data>
<value2>
<xsl:value-of select="key('kType1', normalize-space(value1))/value2"/>
</value2>
<xsl:copy-of select="value3"/>
</data>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
<myxml>
<dataType1>
<value1>
A1
</value1>
<value2>
A2
</value2>
</dataType1>
<dataType1>
<value1>
B1
</value1>
<value2>
B2
</value2>
</dataType1>
<dataType2>
<value1>
A1
</value1>
<value3>
A3
</value3>
</dataType2>
<dataType2>
<value1>
B1
</value1>
<value3>
B3
</value3>
</dataType2>
</myxml>
<data>
<value2>
A2
</value2>
<value3>
A3
</value3>
</data>
<data>
<value2>
B2
</value2>
<value3>
B3
</value3>
</data>
应用于提供的XML文档时:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kType1" match="dataType1" use="normalize-space(value1)"/>
<xsl:template match="dataType2[key('kType1', normalize-space(value1))]">
<data>
<value2>
<xsl:value-of select="key('kType1', normalize-space(value1))/value2"/>
</value2>
<xsl:copy-of select="value3"/>
</data>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
<myxml>
<dataType1>
<value1>
A1
</value1>
<value2>
A2
</value2>
</dataType1>
<dataType1>
<value1>
B1
</value1>
<value2>
B2
</value2>
</dataType1>
<dataType2>
<value1>
A1
</value1>
<value3>
A3
</value3>
</dataType2>
<dataType2>
<value1>
B1
</value1>
<value3>
B3
</value3>
</dataType2>
</myxml>
<data>
<value2>
A2
</value2>
<value3>
A3
</value3>
</data>
<data>
<value2>
B2
</value2>
<value3>
B3
</value3>
</data>
A1
A2
地下一层
地下二层
A1
A3
地下一层
地下三层
生成所需的正确结果:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kType1" match="dataType1" use="normalize-space(value1)"/>
<xsl:template match="dataType2[key('kType1', normalize-space(value1))]">
<data>
<value2>
<xsl:value-of select="key('kType1', normalize-space(value1))/value2"/>
</value2>
<xsl:copy-of select="value3"/>
</data>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
<myxml>
<dataType1>
<value1>
A1
</value1>
<value2>
A2
</value2>
</dataType1>
<dataType1>
<value1>
B1
</value1>
<value2>
B2
</value2>
</dataType1>
<dataType2>
<value1>
A1
</value1>
<value3>
A3
</value3>
</dataType2>
<dataType2>
<value1>
B1
</value1>
<value3>
B3
</value3>
</dataType2>
</myxml>
<data>
<value2>
A2
</value2>
<value3>
A3
</value3>
</data>
<data>
<value2>
B2
</value2>
<value3>
B3
</value3>
</data>
A2
A3
地下二层
地下三层
这是1:1的关系吗?如果存在多个具有相应值1的dataType2,会发生什么情况?