我有mule flow
转换XML
:
HTTP Listener > Logger > XSLT > Logger
这是原始消息:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope/" xmlns:pref="URI_SOAP_WS">
<soap:Body>
<entryXML>
<note>
<to>Totest</to>
<from>Fromtest</from>
<heading>Query</heading>
<body>Update Windows 10</body>
</note>
</entryXML>
</soap:Body>
</soap:Envelope>
我想用XSLT
转换为:
<entryXML>
<note>
<to>Totest</to>
<from>Fromtest</from>
<heading>Query</heading>
<body>Update Windows 10</body>
</note>
<entryXML>
我尝试使用模板:
<xsl:stylesheet version="3.0" xmlns:saxon="http://saxon.sf.net/"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:pref="URI_SOAP_WS">
<xsl:output method="xml" version="1.0" encoding="UTF-8"
indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="/*">
<xsl:value-of select="serialize(.)" />
</xsl:template>
</xsl:stylesheet>
但它从<entryXML>
转换为</soap:Envolve>
。
如何转换<entryXML></entryXML>
的内容?
答案 0 :(得分:1)
以下解决方案基于the answer by jelovirt Kevin Brown has linked to。您可以使用XSLT 3.0(XPath 3.0)serialize
函数或名为saxon:serialize
的Saxon扩展函数,但下面的解决方案更具可移植性,因为它适用于XSLT 1.0。
从身份模板开始,复制与更具体的模板不匹配的所有内容。在您的示例中,这将匹配外部SOAP元素。
然后将entryXML
元素作为特殊序列化模式的起点。 entryXML
内的任何内容都将以默认模式以外的模式处理,只有具有此模式的模板才能与输入匹配。
XSLT样式表
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="entryXML">
<xsl:copy>
<xsl:variable name="nodestring">
<xsl:apply-templates select="@*|node()" mode="serialize"/>
</xsl:variable>
<xsl:value-of select="$nodestring"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="serialize">
<xsl:text><</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
<xsl:apply-templates mode="serialize"/>
<xsl:text></</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
</xsl:template>
<xsl:template match="text()" mode="serialize">
<xsl:value-of select="."/>
</xsl:template>
</xsl:transform>
XML输出
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
xmlns:pref="URI_SOAP_WS"
xmlns:saxon="http://saxon.sf.net/">
<soap:Body>
<entryXML>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
</entryXML>
</soap:Body>
</soap:Envelope>
编辑1
如果有的话,上面的方法不会序列化消息中的属性。如果您还需要保留属性,例如在像
这样的消息中<entryXML>
<note>
<to with="love">Tove</to>
^^^^^^^^^^^ attribute
您需要按照
的方式添加模板<xsl:template match="@*" mode="serialize">
<xsl:text> </xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>="</xsl:text>
<xsl:value-of select="."/>
<xsl:text>"</xsl:text>
</xsl:template>
并在*
模式下更改与serialize
匹配的模板:
<xsl:template match="*" mode="serialize">
<xsl:text><</xsl:text>
<xsl:value-of select="name()"/>
<xsl:apply-templates select="@*" mode="serialize"/>
<xsl:text>></xsl:text>
<xsl:apply-templates mode="serialize"/>
<xsl:text></</xsl:text>
<xsl:value-of select="name()"/>
<xsl:text>></xsl:text>
</xsl:template>
编辑2
警告:上述解决方案仅适用于XSLT 1.0,但它也有缺点,并且无法保证在每种情况下都能正确序列化。
它适用于像你这样的简单案例,但强大的通用序列化需要更多努力,正如Martin Honnen所说的那样。参见例如Evan Lenz's stylesheet用于更复杂的方法。
或者,您可以修改原始的XSLT 3.0样式表(借用上面的一些想法)
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="entryXML/*">
<xsl:value-of select="serialize(.)" />
</xsl:template>
</xsl:stylesheet>
这也将导致更可靠的序列化。