【问题标题】:Does XSLT have a Split() function?XSLT 有 Split() 函数吗?
【发布时间】:2010-09-13 06:49:18
【问题描述】:

我在节点中有一个字符串,我想在 '?' 上拆分字符串并返回数组中的最后一项。

例如,在下面的块中:

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

我想拆分 someNode 值。

编辑: 这是我用来为我的 Asp.Net 页面加载 Xsl 的 VB.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()

更新:这里是an example of splitting XML on a particular node

【问题讨论】:

  • 其实和ASP.Net没什么关系

标签: .net xml vb.net xslt split


【解决方案1】:

如果可以使用 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。唯一已知的 .NET 2.0+ 处理器是 Saxon for .NETIKVMExselt,一个 .NET XSLT 3.0 处理器目前处于测试阶段,以及 XMLPrime XSLT 2.0 处理器。

【讨论】:

  • 唯一的缺点是它需要 XSLT 2.0 :-(
  • 是的,我得到一个“'tokenize()' 是一个未知的 XSLT 函数。”错误
  • 您使用的是哪个处理器?
【解决方案2】:

XSLT 1.0 本身没有拆分功能,但您可以通过 substring-before 和 substring-after 函数实现您想要做的事情。

或者,如果您使用的是 Microsoft XSLT 引擎,则可以使用内联 C#。

【讨论】:

    【解决方案3】:

    我最终使用了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() 时仍然收到“'tokenize()' is an unknown XSLT function.”错​​误。

    【讨论】:

    • 我希望我保留了代码,但是在我以前的雇主那里,我编写了一个 xslt 1.0 函数来获取字符串的第 n 个标记。一旦你了解了函数式编程的概念,这并不难
    【解决方案4】:

    仅作记录,如果您使用 1.0 执行此操作,并且确实需要拆分/标记,则需要 xslt extensions

    【讨论】:

    • 很有趣,我将如何在上面的示例中使用它?
    【解决方案5】:

    使用递归方法:

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

    【讨论】:

    • 工作就像一个魅力。谢谢!
    • 请注意,如果列表中没有标记,该模板将输出一个空的&lt;id&gt; 元素,而不是没有&lt;id&gt; 元素。
    • 我对尝试这个感到非常兴奋,但不幸的是 Firefox 说:“XSLT 转换期间出错:XSLT 样式表(可能)包含递归。”。是的,Firefox 它应该是递归的......呃......
    【解决方案6】:

    .NET 不支持 XSLT 2.0,很遗憾。我很确定它支持 EXSLT,它有一个split() 函数。 Microsoft 在其 EXSLT 的实现上有一个older page

    【讨论】:

      【解决方案7】:

      添加另一种可能性,如果您的模板引擎支持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>
      

      【讨论】:

      • 你在.net中成功使用过这个吗?
      【解决方案8】:

      您可以使用string-beforestring-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> 
      

      【讨论】:

        猜你喜欢
        • 2011-03-21
        • 1970-01-01
        • 2021-08-13
        • 1970-01-01
        • 2018-08-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多