You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

XSLT中如何结合轴使用substring-before函数

Great question! Let's break down how to combine XSLT axes with the substring-before() function to process your test case XML. First, let's start with a valid version of your input XML (I filled in the ellipsis to make it well-formed):

<TestCases>
  <TestCase>
    <Name>TC1</Name>
    <TestCaseElement>
      <Code>
        <Line>InstA=Value1</Line>
      </Code>
    </TestCaseElement>
    <TestCaseElement>
      <Code>
        <Line>InstB=Value2</Line>
        <Line>InstC=Value1</Line>
      </Code>
    </TestCaseElement>
    <TestCaseElement>
      <Code>
        <Line>InstA=Value3</Line>
        <Line>InstC=Value1</Line>
      </Code>
    </TestCaseElement>
  </TestCase>
</TestCases>

The substring-before() function is perfect for extracting the instruction name (like InstA) from each <Line> element, since they follow the [Inst]=[Value] pattern. When paired with XSLT axes, you can scope your processing to specific parts of the XML tree (e.g., the current test case, sibling elements, etc.). Let's walk through two practical examples:


Example 1: Find matching instructions across the entire test case

This XSLT will extract each line's instruction name, then use the ancestor axis to find all other lines in the same test case with the same instruction name:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" indent="yes"/>

  <!-- Start at the root and process each test case -->
  <xsl:template match="/">
    <xsl:apply-templates select="TestCases/TestCase"/>
  </xsl:template>

  <xsl:template match="TestCase">
    <xsl:text>=== Test Case: </xsl:text>
    <xsl:value-of select="Name"/>
    <xsl:text> ===&#10;</xsl:text>
    <xsl:apply-templates select=".//Line"/>
    <xsl:text>&#10;</xsl:text>
  </xsl:template>

  <xsl:template match="Line">
    <!-- Use substring-before to get the instruction name (e.g., "InstA") -->
    <xsl:variable name="current-inst" select="substring-before(., '=')"/>
    <xsl:variable name="current-value" select="substring-after(., '=')"/>

    <xsl:text>Line: </xsl:text>
    <xsl:value-of select="."/>
    <xsl:text> | Instruction: </xsl:text>
    <xsl:value-of select="$current-inst"/>

    <!-- Use ancestor::TestCase to scope search to the current test case -->
    <xsl:variable name="matching-lines" select="ancestor::TestCase//Line[
      substring-before(., '=') = $current-inst 
      and not(generate-id() = generate-id(current()))
    ]"/>

    <xsl:if test="$matching-lines">
      <xsl:text> | Other values in test case: </xsl:text>
      <xsl:for-each select="$matching-lines">
        <xsl:value-of select="substring-after(., '=')"/>
        <xsl:if test="position() != last()">, </xsl:if>
      </xsl:for-each>
    </xsl:if>
    <xsl:text>&#10;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

Key details here:

  • substring-before(., '='): Splits the line text at the = character to isolate the instruction name.
  • ancestor::TestCase: Navigates up the XML tree to the parent <TestCase> node, ensuring we only search for matches within the current test case (not across all test cases).
  • We use generate-id() to exclude the current line itself from the matching results.

Example 2: Count matching instructions in sibling elements

This example uses the following-sibling axis to count how many times InstC appears in subsequent <TestCaseElement> nodes:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" indent="yes"/>

  <xsl:template match="/">
    <xsl:apply-templates select="TestCases/TestCase/TestCaseElement"/>
  </xsl:template>

  <xsl:template match="TestCaseElement">
    <xsl:text>TestCaseElement #</xsl:text>
    <xsl:value-of select="position()"/>
    <!-- Use following-sibling to target subsequent TestCaseElement nodes -->
    <xsl:variable name="instc-in-following" select="following-sibling::TestCaseElement//Line[
      substring-before(., '=') = 'InstC'
    ]"/>
    <xsl:text> | InstC occurrences in following elements: </xsl:text>
    <xsl:value-of select="count($instc-in-following)"/>
    <xsl:text>&#10;</xsl:text>
  </xsl:template>
</xsl:stylesheet>

Key details here:

  • following-sibling::TestCaseElement: Targets all <TestCaseElement> nodes that come after the current one in the XML tree.
  • We pair this with substring-before(., '=') = 'InstC' to filter only lines containing the InstC instruction.

Core Takeaways

  • substring-before() is your go-to for splitting the instruction/value pairs in each line.
  • Axes let you scope your processing to specific parts of the XML tree:
    • ancestor::: Navigate up to parent/grandparent nodes (great for scoping to a test case).
    • following-sibling::/preceding-sibling::: Target sibling nodes before/after the current element.
    • descendant::: Navigate down to all child nodes (.// is a shorthand for descendant-or-self::).
  • Combine them to create powerful, targeted queries across your test case data.

内容的提问来源于stack exchange,提问作者Eduardo Ramírez Gómez

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:06:04