online xslt xslt-1.0 xslt-2.0 xsl-fo

online - cómo analizar el xml dentro de CDATA de otro xml usando xslt?



xslt editor (3)

Necesito transformar el XML dentro del CDATA del XML usando el único XSLT.

Tengo un XML de la siguiente manera con xml dentro de CDATA como en el siguiente 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>

Necesito transformar el xml en:

<?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>

Esta es la salida de muestra que he dado, habría múltiples nodos dentro del xml que necesito atravesar y generar el xml de salida.

Estoy usando el xslt dirigiendo el xpath hacia el nodo dentro del cdata del xml fuente. pero está dando vacío ya que no estaba en un formato de estructura de árbol.

No puedo obtener el X-Path para el xml dentro del CDATA. Está funcionando bien si elimino CDATA en el xml, pero el xml proviene del sistema externo y no se puede modificar.

No puedo usar múltiples xslts. Necesito aplicar solo XSLT.

¿Podrías por favor sugerirme sobre esto?

Muchas gracias de antemano ...


CDATA significa "datos de caracteres", y se utiliza de forma adecuada para indicar que el texto contenido no contiene ningún marcado. Si se utiliza incorrectamente para envolver texto que contiene marcado, la única respuesta es extraer el contenido de texto y pasarlo a una segunda fase de análisis sintáctico. XSLT 1.0 y 2.0 no contienen una función que le permita analizar XML léxico, pero XSLT 3.0 sí lo hace. Si está atascado con XSLT 1.0, tendrá que escribir su propia función de extensión que pasa los datos a un analizador y recupera la raíz del árbol de nodos resultante.


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(., ''&lt;OrgNetworkPlatformID>'')]"> <value> <xsl:value-of select="substring-before(substring-after(., ''&lt;OrgNetworkPlatformID>''), ''&lt;/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>

¿El XML de salida anterior está buscando o algo diferente?


Este XSLT produce la salida requerida:

<?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, ''&gt;'')"> <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(''&lt;/'',$tagName,''&gt;'')"/> </xsl:variable> <xsl:variable name="firstNode"> <xsl:if test="not(contains($topLevelTag,''/&gt;''))"> <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,''/&gt;''))"> <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, ''&gt;'')"> <xsl:variable name="tagWithAttributesWithoutEnd"> <xsl:value-of select="substring-before($text, ''&gt;'')"/> </xsl:variable> <xsl:variable name="tagWithAttributesWithoutBegining"> <xsl:value-of select="substring-after($tagWithAttributesWithoutEnd, ''&lt;'')"/> </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, ''&gt;'')"> <xsl:variable name="tagWithAttributesWithoutEnd"> <xsl:value-of select="substring-before($text, ''&gt;'')"/> </xsl:variable> <xsl:value-of select="concat($tagWithAttributesWithoutEnd,''&gt;'')"/> </xsl:when> </xsl:choose> </xsl:template> <xsl:template name="createAttributes"> <xsl:param name="text"/> <xsl:choose> <xsl:when test="contains($text, ''=&quot;'')"> <xsl:variable name="attributeName"> <xsl:value-of select="substring-before(substring-after($text,'' ''),''=&quot;'')"/> </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,''=&quot;'')),''&quot;'')"/> </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,''=&quot;'',$attributeValue,''&quot;''))"/> </xsl:call-template> </xsl:when> </xsl:choose> </xsl:template> </xsl:stylesheet>