使用 XSL 将 CDATA 中的 XML 溢出到多个块中
Spilt a XML in CDATA into multiple chunks using XSL
我有一个要求,我必须将 SOAP 消息插入到消息字段字符长度为 200 个字符的数据库中。
我必须使用 XSLT 来实现这一点,并且我在 CDATA 部分中获取了 SoapMessage。
下面是我存储在 CDATA 标记中的变量中的 SOAP 消息
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v4="http://www.example.com/ServiceBody/V4">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<v4:getBookDetails>
<v4:Request>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
</book>
</catalog>
</v4:Request>
</v4:getBookDetails>
</soapenv:Body>
</soapenv:Envelope>
下面是我编写的 XSLT,用于将消息放入多个标记中,以便我可以将其插入数据库。
<xsl:stylesheet extension-element-prefixes="date str" exclude-result-prefixes="dp str date" version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="http://exslt.org/dates-and-times" xmlns:str="http://exslt.org/strings">
<xsl:output method="xml"/>
<xsl:template match="/">
<xsl:variable name="cdataVariable">
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:copy-of select="."/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:variable>
<MessageInChunks>
<stringLength><xsl:value-of select="string-length($cdataVariable)"/></stringLength>
<xsl:choose>
<xsl:when test="string-length($cdataVariable) < 200">
<Chunks>
<xsl:copy-of select="$cdataVariable"/>
</Chunks>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="splitMessageIntoChunks">
<xsl:with-param name="messageToSplit">
<xsl:copy-of select="$cdataVariable"/>
</xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</MessageInChunks>
</xsl:template>
<xsl:template name="splitMessageIntoChunks">
<xsl:param name="messageToSplit"/>
<xsl:variable name="chunkSize" select="'200'"/>
<xsl:if test="string-length($messageToSplit) >0">
<Chunks>
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:copy-of select="substring($messageToSplit, 12, $chunkSize)"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</Chunks>
<xsl:call-template name="splitMessageIntoChunks">
<xsl:with-param name="messageToSplit" select="substring($messageToSplit, $chunkSize+1)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
但是我得到的输出不包含期望值的元素,因为子字符串函数的输出不显示元素。
我需要这样的东西。
<MessageInChunks>
<Chunks><![CDATA[<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v4="http://www.example.com/ServiceBody/V4">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<v4:getBookDet]]></Chunks>
<Chunks><![CDATA[ails>
<v4:Request>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Compu]]>
</Chunks>
<Chunks><![CDATA[ter</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
]]>
</Chunks>
<Chunks><![CDATA[ </book>
</catalog>
</v4:Request>
</v4:getBookDetails>
</soapenv:Body>
</soapenv:Envelope>]]>
</Chunks>
</MessageInChunks>
基本上我需要的是将 XML 消息拆分为 200 个字符的块,然后使用 XSLT 将其放入 CDATA 部分。
请帮我解决这个问题。
我认为,首先,您必须摆脱 XML 标签,以便将所有内容都视为一个字符串并将其拆分。
我建议这样做:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="*"> <!-- GET rid of XML tags by replacing them with escaped chars -->
<<xsl:value-of select="name()"/><xsl:for-each select="@*"><xsl:text> </xsl:text><xsl:value-of select="name()"/>="<xsl:value-of select="."/>"</xsl:for-each>><xsl:apply-templates/></<xsl:value-of select="name()"/>>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="everything_in_one_string"><xsl:apply-templates/></xsl:variable> <!-- Put complete output in one variable -->
<xsl:variable name="everything_in_one_string_normalized" as="xs:string" select="normalize-space($everything_in_one_string)"/> <!-- Get rid of whitespace -->
<xsl:variable name="string_length_of_total" as="xs:integer" select="string-length($everything_in_one_string_normalized)"/>
<xsl:variable name="max_string_length_of_substrings" as="xs:integer" select="200"/>
<xsl:variable name="runs_necessary" as="xs:integer" select="ceiling($string_length_of_total div $max_string_length_of_substrings) cast as xs:integer"/>
<!-- Compute how many chunks of 200 chars we need. -->
<MessageInChunks>
<xsl:for-each select="1 to $runs_necessary">
<xsl:variable name="current_run" as="xs:integer" select="."/>
<Chunks><xsl:value-of select="substring($everything_in_one_string_normalized,((($current_run - 1)* $max_string_length_of_substrings) + 1),200)"/></Chunks>
<!-- Always extract 200 chars from the string.
For the first run: Start at 1: ((1 - 1) * 200) + 1 = 0 * 200 + 1 = 1
Second run: ((2 - 1) * 200) + 1 = 1 * 200 + 1 = 201
and so on
-->
</xsl:for-each>
</MessageInChunks>
</xsl:template>
</xsl:stylesheet>
我看到你的问题用 ibm-datapower
标记了。您是 运行 DataPower 设备上的这个 XSLT 吗?如果是这样,您真的应该研究一下 DataPower 扩展元素 dp:serialize
,这将使您的生活更轻松。
看这里:http://www-01.ibm.com/support/knowledgecenter/SS9H2Y_6.0.1/com.ibm.dp.xi.doc/serialize_element.html
我有一个要求,我必须将 SOAP 消息插入到消息字段字符长度为 200 个字符的数据库中。 我必须使用 XSLT 来实现这一点,并且我在 CDATA 部分中获取了 SoapMessage。
下面是我存储在 CDATA 标记中的变量中的 SOAP 消息
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v4="http://www.example.com/ServiceBody/V4">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<v4:getBookDetails>
<v4:Request>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
</book>
</catalog>
</v4:Request>
</v4:getBookDetails>
</soapenv:Body>
</soapenv:Envelope>
下面是我编写的 XSLT,用于将消息放入多个标记中,以便我可以将其插入数据库。
<xsl:stylesheet extension-element-prefixes="date str" exclude-result-prefixes="dp str date" version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="http://exslt.org/dates-and-times" xmlns:str="http://exslt.org/strings">
<xsl:output method="xml"/>
<xsl:template match="/">
<xsl:variable name="cdataVariable">
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:copy-of select="."/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</xsl:variable>
<MessageInChunks>
<stringLength><xsl:value-of select="string-length($cdataVariable)"/></stringLength>
<xsl:choose>
<xsl:when test="string-length($cdataVariable) < 200">
<Chunks>
<xsl:copy-of select="$cdataVariable"/>
</Chunks>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="splitMessageIntoChunks">
<xsl:with-param name="messageToSplit">
<xsl:copy-of select="$cdataVariable"/>
</xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</MessageInChunks>
</xsl:template>
<xsl:template name="splitMessageIntoChunks">
<xsl:param name="messageToSplit"/>
<xsl:variable name="chunkSize" select="'200'"/>
<xsl:if test="string-length($messageToSplit) >0">
<Chunks>
<xsl:text disable-output-escaping="yes"><![CDATA[</xsl:text>
<xsl:copy-of select="substring($messageToSplit, 12, $chunkSize)"/>
<xsl:text disable-output-escaping="yes">]]></xsl:text>
</Chunks>
<xsl:call-template name="splitMessageIntoChunks">
<xsl:with-param name="messageToSplit" select="substring($messageToSplit, $chunkSize+1)"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
但是我得到的输出不包含期望值的元素,因为子字符串函数的输出不显示元素。
我需要这样的东西。
<MessageInChunks>
<Chunks><![CDATA[<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v4="http://www.example.com/ServiceBody/V4">
<soapenv:Header>
</soapenv:Header>
<soapenv:Body>
<v4:getBookDet]]></Chunks>
<Chunks><![CDATA[ails>
<v4:Request>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Compu]]>
</Chunks>
<Chunks><![CDATA[ter</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications with XML.</description>
]]>
</Chunks>
<Chunks><![CDATA[ </book>
</catalog>
</v4:Request>
</v4:getBookDetails>
</soapenv:Body>
</soapenv:Envelope>]]>
</Chunks>
</MessageInChunks>
基本上我需要的是将 XML 消息拆分为 200 个字符的块,然后使用 XSLT 将其放入 CDATA 部分。
请帮我解决这个问题。
我认为,首先,您必须摆脱 XML 标签,以便将所有内容都视为一个字符串并将其拆分。
我建议这样做:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml"/>
<xsl:template match="*"> <!-- GET rid of XML tags by replacing them with escaped chars -->
<<xsl:value-of select="name()"/><xsl:for-each select="@*"><xsl:text> </xsl:text><xsl:value-of select="name()"/>="<xsl:value-of select="."/>"</xsl:for-each>><xsl:apply-templates/></<xsl:value-of select="name()"/>>
</xsl:template>
<xsl:template match="/">
<xsl:variable name="everything_in_one_string"><xsl:apply-templates/></xsl:variable> <!-- Put complete output in one variable -->
<xsl:variable name="everything_in_one_string_normalized" as="xs:string" select="normalize-space($everything_in_one_string)"/> <!-- Get rid of whitespace -->
<xsl:variable name="string_length_of_total" as="xs:integer" select="string-length($everything_in_one_string_normalized)"/>
<xsl:variable name="max_string_length_of_substrings" as="xs:integer" select="200"/>
<xsl:variable name="runs_necessary" as="xs:integer" select="ceiling($string_length_of_total div $max_string_length_of_substrings) cast as xs:integer"/>
<!-- Compute how many chunks of 200 chars we need. -->
<MessageInChunks>
<xsl:for-each select="1 to $runs_necessary">
<xsl:variable name="current_run" as="xs:integer" select="."/>
<Chunks><xsl:value-of select="substring($everything_in_one_string_normalized,((($current_run - 1)* $max_string_length_of_substrings) + 1),200)"/></Chunks>
<!-- Always extract 200 chars from the string.
For the first run: Start at 1: ((1 - 1) * 200) + 1 = 0 * 200 + 1 = 1
Second run: ((2 - 1) * 200) + 1 = 1 * 200 + 1 = 201
and so on
-->
</xsl:for-each>
</MessageInChunks>
</xsl:template>
</xsl:stylesheet>
我看到你的问题用 ibm-datapower
标记了。您是 运行 DataPower 设备上的这个 XSLT 吗?如果是这样,您真的应该研究一下 DataPower 扩展元素 dp:serialize
,这将使您的生活更轻松。
看这里:http://www-01.ibm.com/support/knowledgecenter/SS9H2Y_6.0.1/com.ibm.dp.xi.doc/serialize_element.html