Вопрос

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top