使用XSLT生成SOAP XML的问题
我正在使用XSLT将一些配置XML转换为SOAP请求。但是我很难找到一种不需要完整的XPATH表达式并且仍然生成有效的SOAP XML的方法。使用XSLT生成SOAP XML的问题
以下是配置XML的简化版本。
<CreateOrder>
<client_info>
<name>John Doe</name>
<address>
<street1>1211 Lakeview Dr.</street1>
<city>New York</city>
<state>NY</state>
<country>USA</country>
<zip>12345</zip>
</address>
</client_info>
<subscriber_number>AAANNNDDDD</subscriber_number>
</CreateOrder>
这里是我正在使用的简化XSLT。
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" />
<xsl:template match="/">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<DirectoryNumber><xsl:value-of select="CreateOrder/subscriber_number"/></DirectoryNumber>
<Locale>
<xsl:choose>
<xsl:when test="CreateOrder/client_info/address/country = 'USA'">
<xsl:text>English (US)</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>User Defined 1</xsl:text>
</xsl:otherwise>
</xsl:choose>
</Locale>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
</xsl:stylesheet>
这将生成以下XML输出 - 这是我的预期/想要的。 [请注意,我不得不美化打印此 - 我的输出实际上只是问心无愧不换行/缩进单行]
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<DirectoryNumber>
AAANNNDDDD
</DirectoryNumber>
<Locale>
English (US)
</Locale>
</soapenv:Body>
</soapenv:Envelope>
通过玩耍,看来我需要使用<xsl:template match="/">
整个输入相匹配文档,否则我不会将SOAP XML输入到输出中。有没有其他方法可以从XSLT生成一系列新的XML?
但当<xsl:template match="/">
存在时,我不能嵌套其他<xsl:template match=...">
元件(例如,以匹配“地址”)等具有使用全XPATH表达式节点(如CreateOrder/client_info/address/country
)在试验中。这可行,但并不特别优雅,并且对于真实世界更长的示例而言有点容易出错。有没有更好的方法来做到这一点?
模板不嵌套。您可以在模板的相应位置使用<xsl:apply-templates.../>
实现您想要的效果。在您的简单示例中,不必指定路径,但是在更大,更复杂的样式表中,您可以有许多可重用的模板。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<DirectoryNumber><xsl:value-of select="CreateOrder/subscriber_number"/></DirectoryNumber>
<Locale>
<xsl:apply-templates select="CreateOrder/client_info/address/country"/>
</Locale>
</soapenv:Body>
</soapenv:Envelope>
</xsl:template>
<xsl:template match="country">
<xsl:choose>
<xsl:when test=". = 'USA'">
<xsl:text>English (US)</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>User Defined 1</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
了解XSLT的关键是要认识到它不是程序性的......您的样式表不受控制。相反,XSLT处理器正在检查每个输入标记,然后在样式表中搜索匹配的模板。一旦找到并应用了匹配规则,该标签的处理就完成了。如果您匹配/
,则整个文档将被该模板使用。调用其他模板的唯一方法是通过<xsl:apply-templates select="some xpath"/>
告诉处理器使用“some xpath”选择的节点重新启动匹配过程。样式表中的第一个模板匹配/
是非常常见的。
谢谢吉姆。对XSLT来说很新,我担心我错过了一些东西,或者有更好的方式去做我正在做的事情。因此,接受一个认真解释的“这就是你所做的”答案确实有帮助。我将开始使用apply-templates结构来使代码更清晰/更模块化。 – Torid