我在弄清楚如何使用 XSLT V1 转换将平面 XML 转换为分层结果时遇到了很大的麻烦。 我会发布我的 XSLT,但我不确定我是否正确接近它。 我知道我需要创建和使用Keys,但是,无论尝试应用我在这里和其他地方找到的每个示例(很多,很多,很多......),它根本不起作用。
这是输入:
<env:Envelope xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<tns:getClientRS xmlns:tns="http://services.xxx.com/ClientService">
<tns:Acknowledgement>Process completed successfully.</tns:Acknowledgement>
<tns:client>
<tns:ClientID>515164</tns:ClientID>
<tns:episodeID>1</tns:episodeID>
<tns:guarantorID>1</tns:guarantorID>
</tns:client>
<tns:client>
<tns:ClientID>515164</tns:ClientID>
<tns:episodeID>1</tns:episodeID>
<tns:guarantorID>2</tns:guarantorID>
</tns:client>
<tns:plan>
<tns:ClientID>515164</tns:ClientID>
<tns:episodeID>1</tns:episodeID>
<tns:guarantorID>1</tns:guarantorID>
<tns:guarantorPlan>1</tns:guarantorPlan>
</tns:plan>
<tns:plan>
<tns:ClientID>515164</tns:ClientID>
<tns:episodeID>1</tns:episodeID>
<tns:guarantorID>2</tns:guarantorID>
<tns:guarantorPlan>2</tns:guarantorPlan>
</tns:plan>
</tns:getClientRS>
</env:Body>
</env:Envelope>
和所需的响应 XML:
<env:Envelope xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header/>
<env:Body>
<tns:getClientRS xmlns:tns="http://services.xxx.com/ClientService">
<tns:Acknowledgement>Process completed successfully.</tns:Acknowledgement>
<tns:clients>
<tns:ClientID>515164</tns:ClientID>
<tns:episodes>
<tns:Episode>
<tns:episodeID>1</tns:episodeID>
<tns:Guarantors>
<tns:Guarantor>
<tns:guarantorID>1</tns:guarantorID>
<tns:Plan>
<tns:guarantorPlan>1</tns:guarantorPlan>
</tns:Plan>
</tns:Guarantor>
<tns:Guarantor>
<tns:guarantorID>2</tns:guarantorID>
<tns:Plan>
<tns:guarantorPlan>2</tns:guarantorPlan>
</tns:Plan>
</tns:Guarantor>
</tns:Guarantors>
</tns:Episode>
</tns:episodes>
</tns:clients>
</tns:getClientRS>
</env:Body>
</env:Envelope>
只是想让事情变得简单,但可能会有多个客户端和多个剧集。 我怀疑如果我能弄清楚担保人,我就能弄清楚剧集和客户。
我真的需要这里的帮助。 无论我做什么,我都只得到每个钥匙中的第一个......即担保人 1 和计划 1。 就是这样。
我建议你试试这种方式:
XSLT 1.0 + EXSLT set:distinct()
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:tns="http://services.xxx.com/ClientService"
xmlns:set="http://exslt.org/sets"
extension-element-prefixes="set">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="client" match="tns:client" use="tns:ClientID" />
<xsl:key name="plan" match="tns:plan" use="concat(tns:ClientID, '|', tns:episodeID)" />
<xsl:template match="/">
<env:Envelope xmlns:wsa="http://www.w3.org/2005/08/addressing">
<env:Header/>
<env:Body>
<tns:getClientRS>
<xsl:copy-of select="tns:Acknowledgement"/>
<tns:clients>
<!-- client -->
<xsl:for-each select="set:distinct(env:Envelope/env:Body/tns:getClientRS/tns:client/tns:ClientID)">
<xsl:variable name="clientID" select="." />
<xsl:copy-of select="."/>
<tns:episodes>
<!-- episode -->
<xsl:for-each select="set:distinct(key('client', .)/tns:episodeID)">
<tns:Episode>
<xsl:variable name="episodeID" select="." />
<xsl:copy-of select="."/>
<!-- plans -->
<tns:Guarantors>
<xsl:for-each select="key('plan', concat($clientID, '|', $episodeID))">
<tns:Guarantor>
<xsl:copy-of select="tns:guarantorID"/>
<tns:Plan>
<xsl:copy-of select="tns:guarantorPlan"/>
</tns:Plan>
</tns:Guarantor>
</xsl:for-each>
</tns:Guarantors>
</tns:Episode>
</xsl:for-each>
</tns:episodes>
</xsl:for-each>
</tns:clients>
</tns:getClientRS>
</env:Body>
</env:Envelope>
</xsl:template>
</xsl:stylesheet>
这将返回输入示例的预期结果 - 尽管这可能部分是巧合。如果每个担保人有多个计划,则需要再添加一个级别。
不打算编写整个 XSLT 文件,但您是否尝试过以下方法?
<xsl:foreach select="tns:client">
<xsl:if test="
not( preceding-sibling::tns:getClientRS[
not(./tns:ClientID = current()/tns:ClientID )
] )
">
<xsl:variable name="ClientID" select="tns:ClientID"/>
然后根据需要遍历客户端和计划(即 select="ancestor::tns:getClientRS/tns:plan[tns:ClientId = $ClientID]"
)。