我需要转换以下XML:
<?xml version="1.0" encoding="utf-8"?>
<TestRecords>
<TestData>
<Users>
<User>
<Id>BG123</Id>
<Name>Bill Gates</Name>
</User>
<User>
<Id>SN123</Id>
<Name>Satya Nadella</Name>
</User>
</Users>
<UserDetails>
<UserDetail>
<UserId>SN123</UserId>
<CompanyName>Microsoft Corp</CompanyName>
</UserDetail>
<UserDetail>
<UserId>
<UserId>BG123</UserId>
<CompanyName>Bill Gates Foundation</CompanyName>
</UserId>
</UserDetail>
</UserDetails>
我需要将此XML映射到以下XML:
<?xml version="1.0" encoding="utf-8"?>
<TestRecords>
<TestData>
<Users>
<User>
<Id>BG123</Id>
<Name>Bill Gates</Name>
<CompanyName>Bill Gates Foundation</CompanyName>
</User>
<User>
<Id>SN123</Id>
<Name>Satya Nadella</Name>
<CompanyName>Microsoft Corp</CompanyName>
</User>
</Users>
</TestData>
</TestRecords>
当我遍历用户/用户时,我需要找到UserDetail,其中UserDetail / UserId等于当前用户/ ID
谢谢你,以及最好的问候
迈克尔
答案 0 :(得分:2)
如果您不想按照FCR的建议进行自定义XSLT,那么当您拥有不同的循环结构时,唯一的另一个选择就是拥有一个中间模式和两个映射。
哪个产生
<TestRecords>
<TestData>
<Users>
<User>
<Id>BG123</Id>
<Name>Bill Gates</Name>
<UserDetails>
<UserID>SN123</UserID>
<CompanyName>Microsoft Corp</CompanyName>
</UserDetails>
<UserDetails>
<UserID>BG123</UserID>
<CompanyName>Bill Gates Foundation</CompanyName>
</UserDetails>
</User>
<User>
<Id>SN123</Id>
<Name>Satya Nadella</Name>
<UserDetails>
<UserID>SN123</UserID>
<CompanyName>Microsoft Corp</CompanyName>
</UserDetails>
<UserDetails>
<UserID>BG123</UserID>
<CompanyName>Bill Gates Foundation</CompanyName>
</UserDetails>
</User>
</Users>
</TestData>
</TestRecords>
然后,您可以通过此第二张地图生成所需的结果。
如果第二个列表很大,这将变得非常低效。
答案 1 :(得分:0)
这是xslt
中常见的查找模式,并且还有机会使用xsl:key
创建可以提高大型文档性能的索引。 Refer here如果您需要将.btm
转换为xslt。
(另外,我假设最后一个UserId
元素没有双重包装UserDetails/UserDetail
):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes"/>
<xsl:key name="userLookup"
match="/TestRecords/TestData/UserDetails/UserDetail" use="UserId"/>
<!--identity template - copy everything by default -->
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<!--i.e.match only Users in the first Users/User tree. Actually the explicit
ancestor qualifier is redundant because of the other suppress template -->
<xsl:template match="User[ancestor::Users]">
<User>
<xsl:copy-of select="child::*" />
<CompanyName>
<xsl:value-of select="key('userLookup', Id)/CompanyName"/>
</CompanyName>
</User>
</xsl:template>
<!--Suppress the second userdetails part of the tree entirely -->
<xsl:template match="UserDetails" />
</xsl:stylesheet>