如何在XSLT中用switch case替代嵌套使用xsl:analyze-string?
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,s2for 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:
- No ignored invalid data: The
<xsl:non-matching-substring>block ensures invalid lines trigger errors. - No code bloat: Even with 8+ shapes, the code remains linear and maintainable, avoiding nested
<xsl:analyze-string>calls.
内容的提问来源于stack exchange,提问作者chansey




