我需要使用单个XSLT转换XML的CDATA内的XML。
我有一个XML,如下面的CDATA中的xml,如下面的xml。
<message channel-id="e01db0aa-b3db-4b6c-a055-7a0d5c1d1f20" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" >
<send-parameters>
<agent-parameter multi-valued="false">
<name>Networks</name>
<value><![CDATA[<Networks>
<Network>
<GroupCode>EXTPRI</GroupCode>
<NetworkTypeId>LANI</NetworkTypeId>
<OrgNetworkPlatformName>EON-0cbu0cust12301dcd-D-PCL-0002</OrgNetworkPlatformName>
<OrgNetworkPlatformID>urn:vcloud:network:b7ccfd5f-cfd7-48eb-9dd6-1989b08d7b86</OrgNetworkPlatformID>
</Network>
<Network>
<GroupCode>EXTPRI</GroupCode>
<NetworkTypeId>LANI</NetworkTypeId>
<OrgNetworkPlatformName>ABC-0cbu0cust12301dcd-D-PCL-XYZ</OrgNetworkPlatformName>
<OrgNetworkPlatformID>urn:vcloud:network:b7ccfd5f-cfd7-48eb-9dd6-1989b08d7b86</OrgNetworkPlatformID>
</Network>
</Networks>]]></value>
</agent-parameter>
</send-parameters>
</message>
我需要将xml转换为:
<?xml version="1.0" encoding="UTF-8"?>
<message xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" channel-id="7652d759-4b32-44d4-8a27-9e390f0cae7b">
<send-parameters>
<agent-parameter multi-valued="false">
<name>ExternalPublicOrgNWPlatformID_DDC</name>
<value>EON-0cbu0cust12301dcd-D-PCL-0002</value>
</agent-parameter>
<agent-parameter multi-valued="false">
<name>ExternalPublicOrgNWPlatformID_DS</name>
<value>ABC-0cbu0cust12301dcd-D-PCL-XYZ</value>
</agent-parameter>
</send-parameters>
</message>
这是我给出的示例输出,我需要遍历xml中的多个节点并生成输出xml。
我使用xslt将xpath引导到源xml的cdata内的节点。但它是空的,因为它不是树形结构格式。
我无法在CDATA中获取xml的X-Path。如果我在xml中删除CDATA,但是xml是从外部系统传入的,不能修改它。
我不能使用多个xslts我需要应用单个XSLT。
请你就此提出建议。
非常感谢期待......
答案 0 :(得分:3)
CDATA表示“字符数据”,它适用于表示包含的文本不包含任何标记。如果它被误用于包含包含标记的文本,那么您唯一的答案就是提取文本内容并将其放入解析的第二阶段。 XSLT 1.0和2.0不包含允许您解析词法XML的函数,但XSLT 3.0可以。如果您坚持使用XSLT 1.0,则必须编写自己的扩展函数,将数据传递给解析器并获取生成的节点树的根。
答案 1 :(得分:3)
此XSLT生成所需的输出:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:variable name="cdata"
select="message/send-parameters/agent-parameter/value"/>
<xsl:variable name="parsedXml_">
<xsl:call-template name="parseXml">
<xsl:with-param name="text" select="$cdata"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="parsedXml" select="exsl:node-set($parsedXml_)"/>
<message xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" >
<xsl:attribute name="channel">
<xsl:value-of select="message/@channel-id"/>
</xsl:attribute>
<send-parameters>
<agent-parameter multi-valued="false">
<name>ExternalPublicOrgNWPlatformID_DDC</name>
<value>
<xsl:value-of select="$parsedXml/Networks/Network[1]/OrgNetworkPlatformName"/>
</value>
</agent-parameter>
<agent-parameter multi-valued="false">
<name>ExternalPublicOrgNWPlatformID_DS</name>
<value>
<xsl:value-of select="$parsedXml/Networks/Network[2]/OrgNetworkPlatformName"/>
</value>
</agent-parameter>
</send-parameters>
</message>
</xsl:template>
<xsl:template name="parseXml">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, '>')">
<xsl:variable name="topLevelTag">
<xsl:call-template name="getTopLevelTag">
<xsl:with-param name="text" select="$text"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="openingTag">
<xsl:value-of select="$topLevelTag"/>
</xsl:variable>
<xsl:variable name="tagName">
<xsl:call-template name="getTopLevelTagName">
<xsl:with-param name="text" select="$text"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="closingTag">
<xsl:value-of select="concat('</',$tagName,'>')"/>
</xsl:variable>
<xsl:variable name="firstNode">
<xsl:if test="not(contains($topLevelTag,'/>'))">
<xsl:value-of select="substring-before(substring-after($text,$openingTag),$closingTag)"/>
</xsl:if>
</xsl:variable>
<xsl:variable name="afterFirstNode">
<xsl:choose>
<xsl:when test="not(contains($topLevelTag,'/>'))">
<xsl:value-of select="substring-after($text,concat($firstNode,$closingTag))"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring-after($text,$topLevelTag)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="{$tagName}">
<xsl:call-template name="createAttributes">
<xsl:with-param name="text" select="$topLevelTag"/>
</xsl:call-template>
<xsl:call-template name="parseXml">
<xsl:with-param name="text" select="$firstNode"/>
</xsl:call-template>
</xsl:element>
<xsl:call-template name="parseXml">
<xsl:with-param name="text" select="$afterFirstNode"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="getTopLevelTagName">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, '>')">
<xsl:variable name="tagWithAttributesWithoutEnd">
<xsl:value-of select="substring-before($text, '>')"/>
</xsl:variable>
<xsl:variable name="tagWithAttributesWithoutBegining">
<xsl:value-of select="substring-after($tagWithAttributesWithoutEnd, '<')"/>
</xsl:variable>
<xsl:variable name="tagName">
<xsl:choose>
<xsl:when test="contains($tagWithAttributesWithoutBegining,' ')">
<xsl:value-of
select="substring-before($tagWithAttributesWithoutBegining, ' ')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$tagWithAttributesWithoutBegining"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="$tagName"/>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="getTopLevelTag">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, '>')">
<xsl:variable name="tagWithAttributesWithoutEnd">
<xsl:value-of select="substring-before($text, '>')"/>
</xsl:variable>
<xsl:value-of select="concat($tagWithAttributesWithoutEnd,'>')"/>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="createAttributes">
<xsl:param name="text"/>
<xsl:choose>
<xsl:when test="contains($text, '="')">
<xsl:variable name="attributeName">
<xsl:value-of select="substring-before(substring-after($text,' '),'="')"/>
</xsl:variable>
<xsl:message>
<xsl:value-of select="$text"/>
</xsl:message>
<xsl:variable name="attributeValue">
<xsl:value-of select="substring-before(substring-after($text,concat($attributeName,'="')),'"')"/>
</xsl:variable>
<xsl:attribute name="{$attributeName}">
<xsl:value-of select="$attributeValue"/>
</xsl:attribute>
<xsl:call-template name="createAttributes">
<xsl:with-param name="text" select="substring-after($text,concat($attributeName,'="',$attributeValue,'"'))"/>
</xsl:call-template>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:1)
The below is the transform for the expected output:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="message">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="value">
<xsl:apply-templates select="text()" />
</xsl:template>
<xsl:template match="text()[contains(., '<OrgNetworkPlatformID>')]">
<value>
<xsl:value-of select="substring-before(substring-after(., '<OrgNetworkPlatformID>'),
'</OrgNetworkPlatformID>')"/>
</value>
</xsl:template>
</xsl:stylesheet>
The output xml :
<?xml version="1.0" encoding="utf-8"?>
<message channel-id="e01db0aa-b3db-4b6c-a055-7a0d5c1d1f20" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<send-parameters>
<agent-parameter multi-valued="false">
<name>Networks</name>
<value>urn:vcloud:network:b7ccfd5f-cfd7-48eb-9dd6-1989b08d7b86</value>
</agent-parameter>
</send-parameters>
</message>
您要查找上述输出XML还是其他不同的东西?