我正在尝试使用XSLT进行xml转换。我有以下xml:
<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>
每个datatype2都有一个元素value1,它是datatype2中的一个外键,所以我必须根据value1映射这些数据。
如果dataType1的值为value1 = A1,dataType2的值为value1 = A1,那么我必须创建一个值为value2和value3的xml,结果如下:
<resultxml>
<data>
<value2>
A2
</value2>
<value3>
A3
</value3>
</data>
<data>
<value2>
B2
</value2>
<value3>
B3
</value3>
</data>
我考虑在读取dataType1时动态创建变量,然后在读取datatype2时调用它们,但正如我在某个论坛上读到的那样,这是不可能的,所以我的问题是:可以做我解释的吗?如果是,我必须遵循的方法(欢迎例子)
提前致谢
答案 0 :(得分:1)
这是一个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>
在输入
上应用上述样式表时<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>
使用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>
使用XSLT 1.0,您无法在匹配模式中使用密钥,因此需要更多代码,稍后我将添加示例。
[编辑] 这是一个XSLT 1.0样式表:
<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>
答案 1 :(得分:1)
我的建议
<?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>
答案 2 :(得分:1)
此转化:
<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>
应用于提供的XML文档:
<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>