Pregunta

Tengo una cadena en un nodo y me gustaría dividir la cadena en '?' y devuelve el último elemento de la matriz.

Por ejemplo, en el bloque de abajo:

<a>
    <xsl:attribute name="href">
        /newpage.aspx?<xsl:value-of select="someNode"/>
    </xsl:attribute>
    Link text
</a>

Me gustaría dividir el valor de someNode .

Editar: Aquí está el VB.Net que utilizo para cargar el Xsl para mi página Asp.Net:

Dim xslDocPath As String = HttpContext.Current.Server.MapPath("~/App_Data/someXslt.xsl")
Dim myXsltSettings As New XsltSettings()
Dim myXMLResolver As New XmlUrlResolver()

myXsltSettings.EnableScript = True
myXsltSettings.EnableDocumentFunction = True

myXslDoc = New XslCompiledTransform(False)
myXslDoc.Load(xslDocPath, myXsltSettings, myXMLResolver)

Dim myStringBuilder As New StringBuilder()
Dim myXmlWriter As XmlWriter = Nothing

Dim myXmlWriterSettings As New XmlWriterSettings()
myXmlWriterSettings.ConformanceLevel = ConformanceLevel.Auto
myXmlWriterSettings.Indent = True
myXmlWriterSettings.OmitXmlDeclaration = True

myXmlWriter = XmlWriter.Create(myStringBuilder, myXmlWriterSettings)

myXslDoc.Transform(xmlDoc, argumentList, myXmlWriter)

Return myStringBuilder.ToString()

Actualización: aquí hay un ejemplo de división de XML en un nodo en particular

¿Fue útil?

Solución

Usa un método recursivo:

<xsl:template name="output-tokens">
    <xsl:param name="list" /> 
    <xsl:variable name="newlist" select="concat(normalize-space($list), ' ')" /> 
    <xsl:variable name="first" select="substring-before($newlist, ' ')" /> 
    <xsl:variable name="remaining" select="substring-after($newlist, ' ')" /> 
    <id>
        <xsl:value-of select="$first" /> 
    </id>
    <xsl:if test="$remaining">
        <xsl:call-template name="output-tokens">
            <xsl:with-param name="list" select="$remaining" /> 
        </xsl:call-template>
    </xsl:if>
</xsl:template>

Otros consejos

Si puedes usar XSLT 2.0 o superior, puedes usar tokenize (string, separator) :

tokenize("XPath is fun", "\s+")
Result: ("XPath", "is", "fun")

Consulte la referencia de la función XPath de w3schools .

De manera predeterminada, .NET no admite XSLT 2.0, y mucho menos XSLT 3.0. Los únicos procesadores 2.0+ conocidos para .NET son Saxon para .NET con IKVM , Exselt , un procesador .NET XSLT 3.0 actualmente en versión beta, y XMLPrime del procesador XSLT 2.0.

Terminé usando el substring-after () función. Esto es lo que funcionó para mí:

<a>
    <xsl:attribute name="href">
        /newpage.aspx?<xsl:value-of select="substring-after(someNode, '?')"/>
    </xsl:attribute>
    Link text
</a>

Incluso después de configurar la versión de mi XSLT en 2.0, todavía tengo un " 'tokenize ()' es una función XSLT desconocida. " error al intentar utilizar tokenize () .

Agregando otra posibilidad, si su motor de plantillas es compatible con EXSLT , entonces puede usar tokenize () de eso.

Por ejemplo:

<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:str="http://exslt.org/strings"
                extension-element-prefixes="str">

...
  <a>
    <xsl:attribute name="href">
      <xsl:text>/newpage.aspx?</xsl:text>
      <xsl:value-of select="str:tokenize(someNode)[2]"/>
    </xsl:attribute>              
  </a>
...
</xsl:stylesheet>

.NET no admite XSLT 2.0, desafortunadamente. Estoy bastante seguro de que es compatible con EXSLT, que tiene un split () función. Microsoft tiene una página anterior sobre su implementación de EXSLT.

Puede escribir una plantilla con las funciones string-before y string-after y utilizarla. Escribí un blog sobre esto.

Finalmente surgió una plantilla xslt que dividiría una cadena delimitada en subcadenas. No digo que sea el script más inteligente, pero seguramente resuelve mi problema.

Hoja de estilo:

<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:for-each select="Paths/Item">
<xsl:call-template name="SplitText">
<xsl:with-param name="inputString" select="Path"/>
<xsl:with-param name="delimiter" select="Delimiter"/>
</xsl:call-template>
<br/>
</xsl:for-each>
</xsl:template>
<xsl:template name="SplitText">
<xsl:param name="inputString"/>
<xsl:param name="delimiter"/>
<xsl:choose>
<xsl:when test="contains($inputString, $delimiter)">
<xsl:value-of select="substring-before($inputString,$delimiter)"/>
<xsl:text disable-output-escaping = "no"> </xsl:text>
<xsl:call-template name="SplitText">
<xsl:with-param name="inputString" select="substring-after($inputString,$delimiter)"/>
<xsl:with-param name="delimiter" select="$delimiter"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$inputString = ''">
<xsl:text></xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$inputString"/>
<xsl:text> </xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

archivo XML (a transformar):

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="textSpliter.xslt"?>
<Paths>
  <Item>
    <Path>C:\ProgramFiles\SomeWierdSoftware</Path>
    <Delimiter>\</Delimiter>
  </Item>
</Paths> 

XSLT 1.0 no tiene una función de división per se, pero potencialmente podría lograr lo que está tratando de hacer con las funciones de subcadena antes y de subcadena después.

Alternativamente, si estás usando un motor Microsoft XSLT, puedes usar C # en línea.

Solo para el registro, si está haciendo esto con 1.0, y realmente necesita un split / tokenise, necesita el extensiones xslt .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top