Есть ли в XSLT функция Split()?
Вопрос
У меня есть строка в узле, и я хотел бы разделить строку на '?' и вернуть последний элемент в массиве.
Например, в блоке ниже:
<a>
<xsl:attribute name="href">
/newpage.aspx?<xsl:value-of select="someNode"/>
</xsl:attribute>
Link text
</a>
Я бы хотел разделить someNode
ценность.
Редактировать:Вот VB.Net, который я использую для загрузки Xsl для моей 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()
Обновить: вот пример разделения XML на определенном узле
Решение
Используйте рекурсивный метод:
<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>
Другие советы
Если вы можете использовать XSLT 2.0 или выше, вы можете использовать tokenize(string, separator)
:
tokenize("XPath is fun", "\s+")
Result: ("XPath", "is", "fun")
Посмотрите на ссылка на функцию w3schools XPath.
По умолчанию .NET не поддерживает XSLT 2.0, не говоря уже о XSLT 3.0.Единственными известными процессорами 2.0+ для .NET являются Саксонский для .NET с IKVM, Эксельт, процессор .NET XSLT 3.0, который в настоящее время находится в стадии бета-тестирования, и XMLPrime ( первичный код ) Процессор XSLT 2.0.
В итоге я воспользовался substring-after()
функция.Вот что сработало у меня:
<a>
<xsl:attribute name="href">
/newpage.aspx?<xsl:value-of select="substring-after(someNode, '?')"/>
</xsl:attribute>
Link text
</a>
Даже после установки версии моего XSLT на 2.0, я все еще получаю "'tokenize()' is an unknown XSLT function.
" ошибка при попытке использовать tokenize()
.
Добавляем еще одну возможность, если ваш движок шаблонов поддерживает EXSLT, тогда вы могли бы использовать токенизировать() от этого.
Например:
<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 не поддерживает XSLT 2.0.Я почти уверен, что он поддерживает EXSLT, который имеет сплит() функция.У Microsoft есть более старая страница о своей реализации EXSLT.
Вы можете написать шаблон, используя string-before
и string-after
функции и используйте их повсеместно.Я написал Блог на этом.
Наконец-то появился шаблон xslt, который разбивал строку с разделителями на подстроки.Я не утверждаю, что это самый умный сценарий, но он, безусловно, решает мою проблему.
Таблица стилей:
<?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>
XML-файл (подлежит преобразованию) :
<?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 не имеет функции разделения как таковой, но потенциально вы могли бы достичь того, что пытаетесь сделать, с помощью функций substring-before и substring-after .
В качестве альтернативы, если вы используете движок Microsoft XSLT, вы могли бы использовать встроенный C #.
Просто для справки, если вы делаете это с 1.0, и вам действительно нужно разделение / токенизация, вам нужен расширения xslt.