我必须根据特定的id将xml有效负载复制到尽可能多的xml有效负载中,例如userid
<ns2:Details xmlns:ns2="ns">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
<ns2:UserId>237</ns2:UserId>
</ns2:Details>
我需要输出
<ns2:Details>
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
</ns2:Details>
<ns2:Details>
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>237</ns2:UserId>
</ns2:Details>
这是可能的
更新:以下给出的答案工作正常,但有一点我没注意到。如果用户标识相同且重复,则应显示相同的xml有效负载。为此,我尝试了以下方法来获取userid的独特元素
<xsl:param name="userId" select="ns0:UserId[generate-id(.)=generate-id(key('k', ns0:UserId)[1])]"/>
但这不起作用,也尝试使用上面的
..[generate-id(.)=generate-id(key('k', ns0:UserId)[1])]
在模板级别也无法正常工作
我错过了什么吗?
更新: 我对上面的代码做了一个小修改,而不是在xsl:param上工作,我在xsl上使用它:apply-template
修改前的(作为对我的回答) &lt; xsl:apply-templates select =“// ns2:Details / ns2:UserId”/&gt; 修改后 &lt; xsl:apply-templates select =“// ns2:Details / ns2:UserId [generate-id(。)= generate-id(key('myUserId',。)[1])]”/&gt;
我的错误我使用的是ns2:userid而不是“。”
完整的xsl代码 ---
<xsl:output method="xml" indent="yes"/> <xsl:key name="k" match="ns2:UserId" use="text()"/> <xsl:key name="myUserId" match="ns2:UserId" use="."/> <xsl:template match="/"> <ns2:Root> <xsl:apply-templates select="//ns2:Details/ns2:UserId[generate-id(.)=generate-id(key('myUserId', .)[1])]"/> </ns2:Root> </xsl:template>
<xsl:template match="//ns2:Details"> <xsl:param name="userId" select="ns2:UserId"/> <ns2:Details> <xsl:copy-of select="key('k', $userId)[1]"/> <!-- displays UserId values--> <xsl:copy-of select="./*[name() != 'ns2:UserId']"/> <!-- displays other values--> </ns2:Details> </xsl:template>
<xsl:template match="ns2:UserId"> <xsl:apply-templates select=".."> <xsl:with-param name="userId" select="."/> </xsl:apply-templates> </xsl:template>
请验证它。这也适合我...
答案 0 :(得分:4)
假设XML:
<ns2:Details xmlns:ns2="ns2">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
<ns2:UserId>237</ns2:UserId>
<ns2:UserId>46</ns2:UserId>
</ns2:Details>
XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="ns2"
>
<xsl:output method="xml" indent="yes"/>
<xsl:key name="k" match="ns2:UserId" use="text()"/>
<xsl:template match="/">
<root>
<xsl:apply-templates select="//ns2:Details/ns2:UserId[not(node() = preceding-sibling::node())]"/>
</root>
</xsl:template>
<xsl:template match="//ns2:Details">
<xsl:param name="userId" select="ns2:UserId"/>
<ns2:Details>
<xsl:copy-of select="key('k', $userId)[not(node() = preceding-sibling::node())]"/>
<xsl:copy-of select="./*[name() != 'ns2:UserId']"/>
</ns2:Details>
</xsl:template>
<xsl:template match="ns2:UserId">
<xsl:apply-templates select="..">
<xsl:with-param name="userId" select="."/>
</xsl:apply-templates>
</xsl:template>
</xsl:stylesheet>
输出XML:
<?xml version="1.0" encoding="utf-8"?>
<root xmlns:ns2="ns2">
<ns2:Details>
<ns2:UserId>46</ns2:UserId>
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
</ns2:Details>
<ns2:Details>
<ns2:UserId>237</ns2:UserId>
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
</ns2:Details>
</root>
答案 1 :(得分:1)
此转化(简称,只有两个模板,没有xsl:for-each
,没有模式):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="ns">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kIdByVal" match="ns2:UserId" use="."/>
<xsl:template match="/">
<xsl:apply-templates select=
"ns2:Details/ns2:UserId
[generate-id()=generate-id(key('kIdByVal',.)[1])]
"/>
</xsl:template>
<xsl:template match="ns2:UserId">
<ns2:Details>
<xsl:copy-of select=
"../node()
[not(self::ns2:UserId
[not(generate-id()=generate-id(current()))])
]"/>
</ns2:Details>
</xsl:template>
</xsl:stylesheet>
应用于此XML文档(包含冗余的ns2:UserId
元素):
<ns2:Details xmlns:ns2="ns">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
<ns2:UserId>237</ns2:UserId>
<ns2:UserId>46</ns2:UserId>
</ns2:Details>
产生完全正确的结果:
<ns2:Details xmlns:ns2="ns">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
</ns2:Details>
<ns2:Details xmlns:ns2="ns">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>237</ns2:UserId>
</ns2:Details>
解释:Muenchian分组,xsl:copy-of
,使用current()
答案 2 :(得分:0)
是的,这是可能的。您可以使用for for-each loop使用for-each ns2:UserID节点进行循环。
答案 3 :(得分:0)
实现所需结果的一种方法是使用身份转换并覆盖ns2:Details
节点。
在覆盖模板中,您可以使用重复指令xsl:for-each
来迭代所有UserId
。
要管理重复的UserId
,您可以使用来自Menuchian分组方法的众所周知的谓词。
因为我们将使用身份转换,所以生成所有内容的方式要简单得多。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="ns">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="UserId" match="ns2:UserId" use="."/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns2:Details">
<xsl:for-each select="ns2:UserId
[generate-id()
= generate-id(key('UserId',.)[1])]">
<ns2:Details>
<xsl:copy-of select="../@*"/>
<xsl:apply-templates select="../node()
[not(self::ns2:UserId)]"/>
<xsl:apply-templates select="."/>
</ns2:Details>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
当此变换应用于问题中提供的输入时,将获得以下片段:
<ns2:Details xmlns:ns2="ns">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
</ns2:Details>
<ns2:Details xmlns:ns2="ns">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>237</ns2:UserId>
</ns2:Details>
即使输入文档中存在重复的UserId,也会获得此输出。
答案 4 :(得分:0)
以下样式表处理重复项:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns2="ns2">
<xsl:output method="xml" indent="yes" />
<xsl:key name="byUserId" match="ns2:UserId" use="." />
<xsl:template match="/">
<root>
<xsl:apply-templates
select="ns2:Details/ns2:UserId
[generate-id()=generate-id(key('byUserId', .)[1])]" />
</root>
</xsl:template>
<xsl:template match="ns2:UserId">
<xsl:apply-templates select=".." mode="out">
<xsl:with-param name="userId" select="." />
</xsl:apply-templates>
</xsl:template>
<xsl:template match="ns2:Details" mode="out">
<xsl:param name="userId" select="''" />
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="out" />
<xsl:copy-of select="$userId"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ns2:UserId" mode="out" />
<xsl:template match="node()|@*" mode="out">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="out" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
在此输入上:
<ns2:Details xmlns:ns2="ns2">
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
<ns2:UserId>237</ns2:UserId>
<ns2:UserId>46</ns2:UserId>
</ns2:Details>
产地:
<root xmlns:ns2="ns2">
<ns2:Details>
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>46</ns2:UserId>
</ns2:Details>
<ns2:Details>
<ns2:var1>AA0511201143</ns2:var1>
<ns2:var2>PARCEL</ns2:var2>
<ns2:var3>04/04/2011</ns2:var3>
<ns2:var4>Organization</ns2:var4>
<ns2:UserId>237</ns2:UserId>
</ns2:Details>
</root>
答案 5 :(得分:0)
除了在XSLT 2.0中,它很简单而不是使用apply-templates编写多个temlates,使用单个模板查看下面的代码,它将得到相同的结果。
<xsl:for-each-group select="*:Details" group-by="*:UserId">
<xsl:comment select="current-grouping-key()"/>
<ns2:Details>
<xsl:for-each select="current-group()">
<xsl:element name="ns2:UserId">
<xsl:value-of select="current-grouping-key()"/>
</xsl:element>
<xsl:copy-of select="*[name() != 'ns2:UserId']"/>
</xsl:for-each>
</ns2:Details>
</xsl:for-each-group>
</xsl:template>
答案 6 :(得分:0)
XSLT 1.0上还有两个紧凑版本,结果相同。
基于generate-id()
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="ns">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="k1" match="/ns2:Details/ns2:UserId" use="."/>
<xsl:key name="k2" match="/ns2:Details/ns2:UserId" use="generate-id() = generate-id(key('k1',.)[1])"/>
<xsl:template match = "/">
<xsl:for-each select="key('k2',true())">
<ns:Details>
<xsl:copy-of select="../node()[not(self::ns2:UserId)]"></xsl:copy-of>
<xsl:copy-of select="."/>
</ns:Details>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
基于先前的兄弟姐妹
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="ns">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="k" match="/ns2:Details/ns2:UserId" use="not(node() = preceding-sibling::ns2:UserId/node())"/>
<xsl:template match = "/">
<xsl:for-each select="key('k',true())">
<ns:Details>
<xsl:copy-of select="../node()[not(self::ns2:UserId)]"></xsl:copy-of>
<xsl:copy-of select="."/>
</ns:Details>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>