Есть ли в XSLT функция Split ()? - PullRequest
       29

Есть ли в XSLT функция Split ()?

43 голосов
/ 26 сентября 2008

У меня есть строка в узле, и я хотел бы разбить строку на '?' и вернуть последний элемент в массиве.

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

<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()

Обновление: вот пример разделения XML на конкретный узел

Ответы [ 8 ]

52 голосов
/ 26 сентября 2008

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

<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 голосов
/ 26 сентября 2008

Если вы можете использовать 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 являются Saxon для .NET с IKVM , Exselt , процессор .NET XSLT 3.0, который в настоящее время находится в стадии бета-тестирования, и XMLPrime XSLT 2.0 процессор.

8 голосов
/ 26 сентября 2008

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

6 голосов
/ 19 мая 2010

Добавление еще одной возможности, если ваш шаблонизатор поддерживает 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>
3 голосов
/ 26 сентября 2008

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

2 голосов
/ 28 мая 2011

Вы можете написать шаблон, используя функции 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> 
1 голос
/ 26 сентября 2008

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

1 голос
/ 26 сентября 2008

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...