我有一个XSL样式表,需要针对两个不同的XML输入应用 - 成功响应和错误响应,并为每个输入返回有效的XML。
两个输入文档都具有相同的一般结构。我已尝试使用模板优先级来接近此功能,但这并不像我期望的那样 - 尽管优先级较低,但第一个模板始终在应用。
为什么这个模板优先应用于第二个模板,即使是成功的XML?如果我完全删除第一个模板,则第二个模板可以正确应用。
我能采取更好的方法吗?
成功回应:
<SOAP_Domain_Msg xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<Context>
<Namespace xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"/>
</Context>
<Header/>
<Body>
<GetCustomerResponse>
<Title>Mr</Title>
<FirstName>Test</FirstName>
<Surname>Person</Surname>
</GetCustomerResponse>
</Body>
</SOAP_Domain_Msg>
错误回复:
<SOAP_Domain_Msg xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<Context>
<SOAP_Version>1.1</SOAP_Version>
<Namespace xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"/>
</Context>
<Body>
<soapenv:Fault>
<faultcode>soapenv:Server</faultcode>
<faultstring>2014-04-09T14:16:41: InternalFault</faultstring>
<detail/>
</soapenv:Fault>
</Body>
</SOAP_Domain_Msg>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<xsl:template match="SOAP_Domain_Msg" priority="-1">
<xsl:copy-of select="Body" />
</xsl:template>
<xsl:template match="Body/GetCustomerResponse" priority="0">
<Applicants>
<Applicant1>
<xsl:if test="CustomerID != ''">
<Id>
<xsl:value-of select="CustomerID" />
</Id>
</xsl:if>
<xsl:if test="Title != ''">
<Title>
<xsl:value-of select="Title" />
</Title>
</xsl:if>
<xsl:if test="FirstName != ''">
<Forename1>
<xsl:value-of select="FirstName" />
</Forename1>
</xsl:if>
<xsl:if test="Surname != ''">
<Name>
<xsl:value-of select="Surname" />
</Name>
</xsl:if>
</Applicant1>
</Applicants>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:1)
当您有两个可以同时应用于同一节点的模板时,priority
用于断开关系。
使用样式表,处理将从文档根节点(/
)开始。没有与此节点匹配的显式模板,因此默认行为将启动,即apply-templates
此节点的所有子节点。接下来,模板匹配器将尝试找到可与文档元素匹配的模板(/SOAP_Domain_Msg
)。只有一个这样的模板:
<xsl:template match="SOAP_Domain_Msg" priority="-1">
<xsl:copy-of select="Body" />
</xsl:template>
这样模板就会触发。由于此模板不包含任何apply-templates
指令,因此这是流程的结束,最终结果将是原始Body
元素的副本。
如果您删除此模板,那么您将获得SOAP_Domain_Msg
的默认行为,即apply-templates
给孩子的行为,依此类推。这将达到尝试将模板应用于GetCustomerResponse
的程度,此时您的其他模板将会触发(与此同时,处理器会将默认模板应用于Context
,{{1 }}和Namespace
元素也是如此,但由于它们中没有一个包含任何文本内容,除了空格外,它们不会产生任何明显的输出。)
我会以稍微不同的方式构建一些东西,从身份模板开始(除非你另外说明,否则按原样复制所有内容),然后根据需要添加特殊情况。
Header
您不想更改的内容(故障情况和成功案例中的<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@*|node()" /></xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:apply-templates select="SOAP_Domain_Msg/Body/*" />
</xsl:template>
<xsl:template match="GetCustomerResponse">
<Applicants>
<Applicant1>
<xsl:apply-templates select="CustomerID | Title | FirstName | Surname" />
</Applicant1>
</Applicants>
</xsl:template>
<xsl:template match="CustomerID">
<Id><xsl:apply-templates /></Id>
</xsl:template>
<xsl:template match="FirstName">
<Forename1><xsl:apply-templates /></Forename1>
</xsl:template>
<xsl:template match="Surname">
<Name><xsl:apply-templates /></Name>
</xsl:template>
</xsl:stylesheet>
元素)不需要特定的模板。