包含 CDATA 的 XML 文件的 XSLT 转换
XSLT Tranformation of XML file containing CDATA
我必须使用 XSLT 转换 xml 文件。
我必须在输出中获取输入文件的某些结构,预计 CDATA 元素上存在的某些元素会发生一些变化。
<soapenv:Envelope xmlns:aa="http://example.com"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<aa:importOrder>
<aa:orderNumber>00501010000342</aa:orderNumber>
<aa:data>
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<OrderImport xmlns="http://test.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
<OrderNumber>00501010000342</OrderNumber>
<Application>
<Student>
<DataElement>
<Name>age</Name>
<Type>Int</Type>
<Value>13</Value>
</DataElement>
<DataElement>
<Name>firstName</Name>
<Type>String</Type>
<Value>taha</Value>
</DataElement>
</Student>
</Application>
</OrderImport>
]]>
</aa:data>
</aa:importOrder>
</soapenv:Body>
</soapenv:Envelope>
我的预期输出应该是这样的:
<soapenv:Envelope xmlns:aa="http://example.com"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<aa:importOrder>
<aa:orderNumber>00501010000342</aa:orderNumber>
<aa:data>
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<OrderImport xmlns="http://test.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
<OrderNumber>00501010000342</OrderNumber>
<Application>
<Student>
<DataElement>
<Name>age</Name>
<Type>Int</Type>
**<Value>Other Value</Value>**
</DataElement>
<DataElement>
<Name>firstName</Name>
<Type>String</Type>
**<Value>Other Value</Value>**
</DataElement>
</Student>
</Application>
</OrderImport>
]]>
</aa:data>
</aa:importOrder>
</soapenv:Body>
</soapenv:Envelope>
为此我使用了这个 xsl 文件:
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="DataElement">
<p>
<xsl:apply-template select="name"/>
</p>
</xsl:template>
<xsl:template match="Name | Type">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="Value">
Other Value
</xsl:template>
但我没有得到预期的输出。
提前致谢
要解析 CDATA 中的内部 XML,您可以使用 parse-xml
,然后通过更改元素值的模板推送节点,然后重新序列化并确保定义 aa:data
作为 CDATA 部分元素:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:aa="http://example.com"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" cdata-section-elements="aa:data"/>
<xsl:template match="aa:data">
<xsl:copy>
<xsl:variable name="transformed">
<xsl:apply-templates select="parse-xml(replace(., '^\s+', ''))/node()"/>
</xsl:variable>
<xsl:value-of select="serialize($transformed, map { 'method' : 'xml', 'omit-xml-declaration' : false() })"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Value" xpath-default-namespace="http://test.com">
<xsl:copy>Other Value</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我必须使用 XSLT 转换 xml 文件。
我必须在输出中获取输入文件的某些结构,预计 CDATA 元素上存在的某些元素会发生一些变化。
<soapenv:Envelope xmlns:aa="http://example.com"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<aa:importOrder>
<aa:orderNumber>00501010000342</aa:orderNumber>
<aa:data>
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<OrderImport xmlns="http://test.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
<OrderNumber>00501010000342</OrderNumber>
<Application>
<Student>
<DataElement>
<Name>age</Name>
<Type>Int</Type>
<Value>13</Value>
</DataElement>
<DataElement>
<Name>firstName</Name>
<Type>String</Type>
<Value>taha</Value>
</DataElement>
</Student>
</Application>
</OrderImport>
]]>
</aa:data>
</aa:importOrder>
</soapenv:Body>
</soapenv:Envelope>
我的预期输出应该是这样的:
<soapenv:Envelope xmlns:aa="http://example.com"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header/>
<soapenv:Body>
<aa:importOrder>
<aa:orderNumber>00501010000342</aa:orderNumber>
<aa:data>
<![CDATA[
<?xml version="1.0" encoding="UTF-8"?>
<OrderImport xmlns="http://test.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema">
<OrderNumber>00501010000342</OrderNumber>
<Application>
<Student>
<DataElement>
<Name>age</Name>
<Type>Int</Type>
**<Value>Other Value</Value>**
</DataElement>
<DataElement>
<Name>firstName</Name>
<Type>String</Type>
**<Value>Other Value</Value>**
</DataElement>
</Student>
</Application>
</OrderImport>
]]>
</aa:data>
</aa:importOrder>
</soapenv:Body>
</soapenv:Envelope>
为此我使用了这个 xsl 文件:
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="DataElement">
<p>
<xsl:apply-template select="name"/>
</p>
</xsl:template>
<xsl:template match="Name | Type">
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="Value">
Other Value
</xsl:template>
但我没有得到预期的输出。
提前致谢
要解析 CDATA 中的内部 XML,您可以使用 parse-xml
,然后通过更改元素值的模板推送节点,然后重新序列化并确保定义 aa:data
作为 CDATA 部分元素:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:aa="http://example.com"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output method="xml" cdata-section-elements="aa:data"/>
<xsl:template match="aa:data">
<xsl:copy>
<xsl:variable name="transformed">
<xsl:apply-templates select="parse-xml(replace(., '^\s+', ''))/node()"/>
</xsl:variable>
<xsl:value-of select="serialize($transformed, map { 'method' : 'xml', 'omit-xml-declaration' : false() })"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Value" xpath-default-namespace="http://test.com">
<xsl:copy>Other Value</xsl:copy>
</xsl:template>
</xsl:stylesheet>