使用XSLT将数据从XML节点合并到另一个节点
问题描述:
使用XSLT,我想弄清楚如何合并/更新一组节点中的数据与另一组节点中的数据。节点具有相同的模式,但父母不同。数据需要根据共享的父属性进行合并。在下面的示例中,数据正在从主体复制到驱动程序。有人可以帮我从这里出去吗?使用XSLT将数据从XML节点合并到另一个节点
输入文件:
<Info>
<Principal id="Insured">
<PersonName>
<GivenName>Jane</GivenName>
<OtherGivenName>A</OtherGivenName>
<Surname>Doe</Surname>
</PersonName>
<PersonInfo>
<BirthDate>01-01-1980</BirthDate>
<MaritalStatus>M</MaritalStatus>
</PersonInfo>
<PrincipalInfo></PrincipalInfo>
</Principal>
<Policy>
<Driver id="Insured">
<PersonName>
<GivenName>Jane</GivenName>
<Surname>Smith</Surname>
</PersonName>
<PersonInfo>
<BirthDate>01-01-1980</BirthDate>
<MaritalStatus>S</MaritalStatus>
<Occupation>Manager</Occupation>
</PersonInfo>
</Driver>
<PolicyInfo></PolicyInfo>
</Policy>
</Info>
所需的结果:
<Info>
<Principal id="Insured">
<PersonName>
<GivenName>Jane</GivenName>
<OtherGivenName>A</OtherGivenName>
<Surname>Doe</Surname>
</PersonName>
<PersonInfo>
<BirthDate>01-01-1980</BirthDate>
<MaritalStatus>M</MaritalStatus>
</PersonInfo>
<PrincipalInfo></PrincipalInfo>
</Principal>
<Policy>
<Driver id="Insured">
<PersonName>
<GivenName>Jane</GivenName>
<OtherGivenName>A</OtherGivenName>
<Surname>Doe</Surname>
</PersonName>
<PersonInfo>
<BirthDate>01-01-1980</BirthDate>
<MaritalStatus>M</MaritalStatus>
<Occupation>Manager</Occupation>
</PersonInfo>
</Driver>
<PolicyInfo></PolicyInfo>
</Policy>
</Info>
答
这里是一个完整的解决方案:
<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="kPrincipalById" match="Principal"
use="@id"/>
<xsl:key name="kPrincipalChild" match="Principal/*/*"
use="concat(../../@id, name())"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Driver/*">
<xsl:variable name="vPrincipal"
select="key('kPrincipalById', ../@id)"/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select=
"$vPrincipal/*[name()=name(current())]/*"/>
<xsl:apply-templates select=
"*[not(key('kPrincipalChild',
concat(../../@id,name())
)
)
]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当这种转变是在所提供的XML文档应用:
<Info>
<Principal id="Insured">
<PersonName>
<GivenName>Jane</GivenName>
<OtherGivenName>A</OtherGivenName>
<Surname>Doe</Surname>
</PersonName>
<PersonInfo>
<BirthDate>01-01-1980</BirthDate>
<MaritalStatus>M</MaritalStatus>
</PersonInfo>
<PrincipalInfo></PrincipalInfo>
</Principal>
<Policy>
<Driver id="Insured">
<PersonName>
<GivenName>Jane</GivenName>
<Surname>Smith</Surname>
</PersonName>
<PersonInfo>
<BirthDate>01-01-1980</BirthDate>
<MaritalStatus>S</MaritalStatus>
<Occupation>Manager</Occupation>
</PersonInfo>
</Driver>
<PolicyInfo></PolicyInfo>
</Policy>
</Info>
想要的,正确的结果产生:
<Info>
<Principal id="Insured">
<PersonName>
<GivenName>Jane</GivenName>
<OtherGivenName>A</OtherGivenName>
<Surname>Doe</Surname>
</PersonName>
<PersonInfo>
<BirthDate>01-01-1980</BirthDate>
<MaritalStatus>M</MaritalStatus>
</PersonInfo>
<PrincipalInfo/>
</Principal>
<Policy>
<Driver id="Insured">
<PersonName>
<GivenName>Jane</GivenName>
<OtherGivenName>A</OtherGivenName>
<Surname>Doe</Surname>
</PersonName>
<PersonInfo>
<BirthDate>01-01-1980</BirthDate>
<MaritalStatus>M</MaritalStatus>
<Occupation>Manager</Occupation>
</PersonInfo>
</Driver>
<PolicyInfo/>
</Policy>
</Info>
说明:
的identity rule /模板拷贝的每一个节点 “原样” 。身份规则的使用和重写是最基本和最强大的XSLT设计模式。
只有一个附加模板覆盖子标识规则 -
Driver
的元素。它复制(并有效地替换Driver
的同名grand-child元素与相应的)Principal
的grand-child元素。然后,它仍然处理(份)的Driver
那些盛大的子元素没有相应的盛大儿童和Principal
元素方便地访问
Principal
其盛大的孩子 - 通过ID和id ++名称(),有两个keys定义为并使用。
这是真的吗?你基本上用新值替换PersonName。没有合并发生。 – Flack 2011-02-12 16:42:06
驱动程序子节点中可能存在额外的节点,我想离开,因此只更换整个节点不起作用。注意我的例子中的。 –
2011-02-12 17:02:45