【问题标题】:split xml value with xpath and check string position使用 xpath 拆分 xml 值并检查字符串位置
【发布时间】:2011-08-03 18:55:52
【问题描述】:

我有以下 xml 文件:

 <courses>
   <course>
    <name>Course 1</name>
    <code>00162</code>
    <questions>2,2,1,1,2,1,1,1</questions>
   </course>
   </courses>

我需要查询文件(我正在使用 xpath)来拆分 'questions' 元素,检查每个数字出现的位置并检查它是数字 1 还是 2。

基本上我需要在 xpath 中这样做:

Dim ints As String() = QuestionsString.ToString.Split(",")
Dim i As Integer

        For i = 0 To UBound(ints)    
            If ints(i) = "2" Then
             'do something
            Else
            'do something else
            End If
        Next

来自 cmets 的更新

您好,谢谢。我打算编辑 问题,因为它是不正确的。我想要 例如,获取所有课程名称 和“问题”元素的代码 (拆分后)第二个有“2” 位置,如 1,2,2,1,1,1,2,1 谢谢!

【问题讨论】:

    标签: xml xpath split


    【解决方案1】:

    在 XSLT 1.0 中,您将使用递归模板来拆分字符串。

    借用@Tomalak's answer to a similar question,就是一个例子:

    <?xml version="1.0"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="/">
        <!--Call the recursive template to split the string-->
            <xsl:call-template name="split">
                <xsl:with-param name="list" select="/courses/course/questions" />
            </xsl:call-template>
        </xsl:template>
    
        <xsl:template name="split">
            <xsl:param name="list"      select="''" />
            <xsl:param name="separator" select="','" />
            <xsl:if test="not($list = '' or $separator = '')">
                <xsl:variable name="head" select="substring-before(concat($list, $separator), $separator)" />
                <xsl:variable name="tail" select="substring-after($list, $separator)" />
    
                <!--Use the parsed value to do something-->
                <xsl:call-template name="handleQuestion">
                    <xsl:with-param name="value" select="$head"/>
                </xsl:call-template>
    
                <xsl:call-template name="split">
                    <xsl:with-param name="list"      select="$tail" />
                    <xsl:with-param name="separator" select="$separator" />
                </xsl:call-template>
            </xsl:if>
        </xsl:template>
    
        <xsl:template name="handleQuestion">
            <xsl:param name="value" />
            <xsl:choose>
                <xsl:when test="$value=2">
                    <!--Do something-->
                </xsl:when>
                <xsl:otherwise>
                    <!--Do something else-->
                </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
    </xsl:stylesheet>
    

    在 XSLT 2.0 中,您可以使用 tokenize() function:

    <?xml version="1.0"?>
    <xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:fn="http://www.w3.org/2005/xpath-functions"
        xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xsl:template match="/">
            <xsl:for-each select="tokenize(/courses/course/questions,',')">
                <xsl:choose>
                    <xsl:when test="number(.)=2">
                        <!--Do something-->
                    </xsl:when>
                    <xsl:otherwise>
                        <!--Do something else-->
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
        </xsl:template>
    </xsl:stylesheet>
    

    【讨论】:

    • ...你有没有 string-join 的递归模板?
    • 当然,像这样:&lt;xsl:template name="string-join"&gt; &lt;xsl:param name="items" select="''" /&gt; &lt;xsl:param name="separator" select="','" /&gt; &lt;xsl:variable name="tail" select="$items[position() &gt; 1]" /&gt; &lt;xsl:value-of select="$items[1]"/&gt; &lt;xsl:if test="$tail"&gt; &lt;xsl:value-of select="$separator"/&gt; &lt;xsl:call-template name="string-join"&gt; &lt;xsl:with-param name="items" select="$tail" /&gt; &lt;xsl:with-param name="separator" select="$separator" /&gt; &lt;/xsl:call-template&gt; &lt;/xsl:if&gt; &lt;/xsl:template&gt;
    【解决方案2】:
    /courses
       /course[
          substring-before(
             substring-after(
                question,
                ','
             ),
             ','
          ) = 2
       ]/*[self::name|self::code]
    

    或者

    /courses
       /course[
          substring(question,3,1) = '2'
       ]/*[self::name|self::code]
    

    【讨论】:

      【解决方案3】:

      XPath 中有tokenize(string, pattern),所以你可以写

      /courses/course/questions[(tokenize(text(), "[0-9]+")) ]
                           put something clever here -------^
      

      但我不明白你所说的“做某事”和“做其他事情”是什么意思。 XPath 用于选择节点/检索信息。您需要 XSLT 或 XQuery 来“做某事”。

      【讨论】:

      • 您好,谢谢。我打算编辑这个问题,因为它不正确。例如,我想获取其“问题”元素(拆分后)在第二个位置具有“2”的所有课程名称和代码,如 1,2,2,1,1, 1,2,1 谢谢!
      猜你喜欢
      • 2013-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多