2008-09-25 7 views
42

У меня есть строка в узле, и я хотел бы разбить строку на '?' и возвращает последний элемент в массиве.Имеет ли XSLT функцию Split()?

Например, в приведенном ниже блоке:

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

Я хотел бы разделить значение someNode.

Edit: Вот 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() 

Update: здесь an example of splitting XML on a particular node

+3

ли на самом деле не имеет ничего общего с ASP.Net – Ikke 2009-11-10 12:34:08

ответ

51

Используйте рекурсивный метод:

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

Если вы можете использовать XSLT 2.0 или выше, вы можете использовать tokenize(string, separator):

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

См w3schools XPath function reference.

По умолчанию .NET не поддерживает XSLT 2.0, не говоря уже о XSLT 3.0. Единственными известными процессорами 2.0+ для .NET являются Saxon for .NET с IKVM, Exselt, процессором .NET XSLT 3.0 в настоящее время в бета-версии и XMLPrime процессором XSLT 2.0.

+4

Только вниз сторона в том, что она требует XSLT 2.0 :-( – 2008-09-25 22:22:20

+1

Да, я получаю «tokenize()» - неизвестная функция XSLT. »Error – travis 2008-09-25 23:16:09

+0

Какой процессор вы используете? – 2008-09-26 15:32:47

1

XSLT 1.0 не имеет функции разделения как таковой, но вы можете потенциально достичь того, что вы пытаетесь сделать с помощью функций substring-before и substring-after.

В качестве альтернативы, если вы используете механизм Microsoft XSLT, вы можете использовать встроенный C#.

8

В итоге я использовал функцию 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().

+0

Хотелось бы, чтобы я сохранил код, но t мой предыдущий работодатель Я написал функцию xslt 1.0, чтобы получить n-й токен строки. Это не так сложно, как только вы оберните голову вокруг функционального программирования концепции – Moe 2008-09-26 18:06:12

1

Только для записи, если вы делаете это с 1.0, вам действительно нужен раскол/токенизация, вам нужен xslt extensions.

3

.NET не поддерживает XSLT 2.0, к сожалению. Я уверен, что он поддерживает EXSLT, который имеет функцию split(). У Microsoft есть older page на реализацию EXSLT.

6

Добавление другой возможности, если ваш движок поддерживает EXSLT, вы можете использовать tokenize().

Например:

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

Вы можете написать шаблон, используя string-before и string-after функции и использовать его в поперечнике. Я написал об этом blog.

Наконец-то появился шаблон 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> 
Смежные вопросы