XSLT a-t-il une fonction Split ()?
Question
J'ai une chaîne dans un nœud et j'aimerais diviser la chaîne en "?" et renvoyer le dernier élément du tableau.
Par exemple, dans le bloc ci-dessous:
<a>
<xsl:attribute name="href">
/newpage.aspx?<xsl:value-of select="someNode"/>
</xsl:attribute>
Link text
</a>
J'aimerais diviser la valeur someNode
.
Modifier: Voici le VB.Net que je utilise pour charger le XSL pour ma page 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()
Mise à jour: voici un exemple de fractionnement XML sur un noeud particulier
La solution
Utilisez une méthode récursive:
<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>
Autres conseils
Si vous pouvez utiliser XSLT version 2.0 ou ultérieure, vous pouvez utiliser tokenize (chaîne, séparateur)
:
tokenize("XPath is fun", "\s+")
Result: ("XPath", "is", "fun")
Voir la référence à la fonction wathschools XPath .
Par défaut, .NET ne prend pas en charge XSLT 2.0, encore moins XSLT 3.0. Les seuls processeurs 2.0+ connus de .NET sont Saxon pour .NET avec IKVM , Exselt , un processeur .NET XSLT 3.0 actuellement en version bêta et processeur XMLPrime XSLT 2.0.
J'ai fini par utiliser le substring-after ()
. Voici ce qui a fonctionné pour moi:
<a>
<xsl:attribute name="href">
/newpage.aspx?<xsl:value-of select="substring-after(someNode, '?')"/>
</xsl:attribute>
Link text
</a>
Même après avoir défini la version de mon XSLT sur 2.0, il me restait un "" tokenize () "est une fonction XSLT inconnue.
" quot; erreur en essayant d'utiliser tokenize ()
.
En ajoutant une autre possibilité, si votre moteur de modèle prend en charge EXSLT , vous pouvez utiliser tokenize () à partir de cela.
Par exemple:
<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 ne supporte malheureusement pas XSLT 2.0. Je suis sûr qu'il prend en charge EXSLT, qui possède un split () fonction. Microsoft a une ancienne page sur son implémentation de EXSLT.
Vous pouvez écrire un modèle en utilisant les fonctions string-before
et string-after
et l'utiliser pour tous les styles. J'ai écrit un blog sur ce sujet.
Enfin, nous avons créé un modèle xslt permettant de scinder une chaîne délimitée en sous-chaînes. Je ne prétends pas que c'est le script le plus intelligent, mais ça règle sûrement mon problème.
Feuille de style:
<?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>
Fichier XML (à transformer):
<?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 n'a pas de fonction divisée en soi, mais vous pouvez potentiellement réaliser ce que vous essayez de faire avec les fonctions substring-before et substring-after.
Si vous utilisez un moteur Microsoft XSLT, vous pouvez également utiliser le C # inline.
Pour mémoire, si vous faites cela avec la version 1.0 et que vous avez vraiment besoin d'un split / tokenise, vous avez besoin du extensions xslt .