Does XSLT têm uma função Split ()?
Pergunta
Eu tenho uma string em um nó e eu gostaria de dividir a string em '?' e retornar o último item na matriz.
Por exemplo, no bloco abaixo:
<a>
<xsl:attribute name="href">
/newpage.aspx?<xsl:value-of select="someNode"/>
</xsl:attribute>
Link text
</a>
Eu gostaria de dividir o valor someNode
.
Edit: Aqui está o VB.Net que eu uso para carregar o XSL para minha 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()
Update: aqui está um exemplo de XML divisão em um nó específico
Solução
Use um 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>
Outras dicas
Se você pode usar XSLT 2.0 ou superior, você pode usar tokenize(string, separator)
:
tokenize("XPath is fun", "\s+")
Result: ("XPath", "is", "fun")
Veja a w3schools XPath referência de função .
Por padrão, o .NET não suporta XSLT 2.0, muito menos XSLT 3.0. Os conhecidos apenas 2.0 + processadores para .NET são Saxon for .NET com IKVM , Exselt , um processador 3.0 .NET XSLT actualmente em beta, e XMLPrime XSLT 2,0 processador.
Acabei usando a função substring-after()
. Aqui está o que funcionou para mim:
<a>
<xsl:attribute name="href">
/newpage.aspx?<xsl:value-of select="substring-after(someNode, '?')"/>
</xsl:attribute>
Link text
</a>
Mesmo depois de definir a versão do meu XSLT a 2,0, eu ainda tenho um erro "'tokenize()' is an unknown XSLT function.
" ao tentar usar tokenize()
.
Adicionando uma outra possibilidade, se o seu motor suportes modelo EXSLT , então você poderia usar tokenize () daquele
Por exemplo:
<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 não suporta XSLT 2.0, infelizmente. Tenho certeza que ele suporta EXSLT, que tem um href="http://www.exslt.org/str/functions/split/str.split.html" rel="nofollow noreferrer"> divisão . Microsoft tem um href="http://msdn.microsoft.com/en-us/library/aa468553.aspx" rel="nofollow noreferrer"> página mais velhos
Você pode escrever um modelo usando funções string-before
e string-after
e usá-lo de vista. Eu escrevi um blogue sobre isso.
Finalmente surgiu com um modelo XSLT que iria dividir uma cadeia delimitada em substrings. Não tenho a pretensão é o roteiro mais inteligente, mas certamente resolve o meu problema.
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>
arquivo XML (para ser transformado):
<?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ão tem uma função split per se, mas você poderia conseguir o que você está tentando fazer com o substring-antes e substring-after funções.
Como alternativa, se você estiver usando um motor Microsoft XSLT, você poderia usar em linha C #.
Apenas para o registro, se você está fazendo isso com 1.0, e você realmente precisa de um grupo / tokenise, é necessário o xslt extensões .