You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在XSLT中用switch case替代嵌套使用xsl:analyze-string?

Handling Shape String Parsing with Switch-Case Logic in XSLT

Absolutely! In XSLT (especially versions 2.0 and later), you can implement switch-case-like behavior alongside <xsl:analyze-string> to parse your shape strings cleanly—fixing both the error handling gaps and code bloat from your original approaches.

XSLT 2.0 Solution (Using <xsl:choose>)

XSLT 2.0 doesn't have a dedicated switch statement, but you can use <xsl:choose> (the equivalent of if-else-if) combined with a single <xsl:analyze-string> call that matches all valid shape patterns in one regex. This avoids redundant analyze-string calls and ensures invalid lines trigger errors.

Here's how to implement it:

<xsl:for-each select="$lines">
  <!-- Single regex that matches all valid shape formats -->
  <xsl:analyze-string select="." regex="^(segment):\s*(\w+)$|^(triangle):\s*(\w+)\s+(\w+)\s+(\w+)$|^(rectangle):\s*(\w+)\s+(\w+)\s+(\w+)\s+(\w+)$">
    <xsl:matching-substring>
      <!-- Use xsl:choose to branch based on which shape was matched -->
      <xsl:choose>
        <!-- Match segment: capture group 1 is "segment", group 2 is the measurement -->
        <xsl:when test="regex-group(1)">
          <segment seg1="{regex-group(2)}"/>
        </xsl:when>
        <!-- Match triangle: capture group 3 is "triangle", groups 4-6 are measurements -->
        <xsl:when test="regex-group(3)">
          <triangle seg1="{regex-group(4)}" seg2="{regex-group(5)}" seg3="{regex-group(6)}"/>
        </xsl:when>
        <!-- Match rectangle: capture group 7 is "rectangle", groups 8-11 are measurements -->
        <xsl:when test="regex-group(7)">
          <rectangle seg1="{regex-group(8)}" seg2="{regex-group(9)}" seg3="{regex-group(10)}" seg4="{regex-group(11)}"/>
        </xsl:when>
      </xsl:choose>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
      <!-- Throw an error for invalid lines instead of ignoring them -->
      <xsl:message terminate="yes">
        Error: Invalid line format detected: <xsl:value-of select="."/>
      </xsl:message>
    </xsl:non-matching-substring>
  </xsl:analyze-string>
</xsl:for-each>

Key Benefits:

  • Single pass parsing: No repeated <xsl:analyze-string> calls, improving efficiency.
  • Explicit error handling: Invalid lines trigger a terminating error instead of being silently ignored.
  • Scalable: Adding a new shape only requires extending the regex and adding a new <xsl:when> block—no messy nesting.

XSLT 3.0 Solution (Using <xsl:switch> + Named Capture Groups)

XSLT 3.0 simplifies this further with the <xsl:switch> statement (true switch-case behavior) and named regex capture groups, making the code far more readable and maintainable.

Here's the optimized version:

<xsl:for-each select="$lines">
  <!-- Regex with named groups for shape type and measurements -->
  <xsl:analyze-string select="." regex="^(?<shape>segment):\s*(?<s1>\w+)$|^(?<shape>triangle):\s*(?<s1>\w+)\s+(?<s2>\w+)\s+(?<s3>\w+)$|^(?<shape>rectangle):\s*(?<s1>\w+)\s+(?<s2>\w+)\s+(?<s3>\w+)\s+(?<s4>\w+)$">
    <xsl:matching-substring>
      <!-- Use xsl:switch to branch on the named "shape" group -->
      <xsl:switch select="regex-group('shape')">
        <xsl:case select="'segment'">
          <segment seg1="{regex-group('s1')}"/>
        </xsl:case>
        <xsl:case select="'triangle'">
          <triangle seg1="{regex-group('s1')}" seg2="{regex-group('s2')}" seg3="{regex-group('s3')}"/>
        </xsl:case>
        <xsl:case select="'rectangle'">
          <rectangle seg1="{regex-group('s1')}" seg2="{regex-group('s2')}" seg3="{regex-group('s3')}" seg4="{regex-group('s4')}"/>
        </xsl:case>
      </xsl:switch>
    </xsl:matching-substring>
    <xsl:non-matching-substring>
      <xsl:message terminate="yes">
        Error: Invalid line format detected: <xsl:value-of select="."/>
      </xsl:message>
    </xsl:non-matching-substring>
  </xsl:analyze-string>
</xsl:for-each>

Key Improvements Over XSLT 2.0:

  • Named capture groups: No need to track numeric group indices—use intuitive names like shape, s1, s2 for clarity.
  • <xsl:switch>: More concise and readable than nested <xsl:when> blocks, aligning with traditional switch-case logic.
  • Easier scalability: Adding a new shape just requires updating the regex with a new named group branch and a corresponding <xsl:case>.

Final Notes

Both approaches solve your original problems:

  1. No ignored invalid data: The <xsl:non-matching-substring> block ensures invalid lines trigger errors.
  2. No code bloat: Even with 8+ shapes, the code remains linear and maintainable, avoiding nested <xsl:analyze-string> calls.

内容的提问来源于stack exchange,提问作者chansey

火山引擎 最新活动