使用XSLT将固定长度文本转换为自定义结构XML的实现问题求助
Let's work through this together! Your current XSLT has a couple of key issues that are stopping it from producing the XML you need, plus it doesn't handle the substring extraction required for your fixed-length input text. Here's a breakdown of what went wrong and how to fix it:
What's Wrong With Your Current XSLT?
- You're using
<xs:element>(an XML Schema element) instead of<xsl:element>(the XSLT tag for generating output nodes). These are completely different—<xs:element>is for defining schema structures, not building your output XML. - Your template is named
main, but there's no logic to trigger it (like a root-matching template that calls it). - There's no code to process your input text at all; you're just hardcoding a static value instead of extracting substrings.
Corrected XSLT Code
This code handles both scenarios: if your input is wrapped in an XML element, or if you're working directly with the plain text string. It uses fixed-position substring extraction to map your input to the desired XML structure:
<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <!-- Indent for readability --> <!-- Scenario 1: Input is an XML element (e.g., <input>abc01223jan20212605 mytext</input>) --> <xsl:template match="/input"> <bookings> <!-- Extract first 3 characters for <name> --> <name><xsl:value-of select="substring(., 1, 3)"/></name> <!-- Extract characters 4-6, replace '0' with 'o' to match your example's <uid>o12</uid> --> <uid><xsl:value-of select="replace(substring(., 4, 3), '0', 'o')"/></uid> <!-- Extract 9 characters starting at position 7 for <date> --> <date><xsl:value-of select="substring(., 7, 9)"/></date> <!-- Extract 4 characters starting at position 16 for <seq> --> <seq><xsl:value-of select="substring(., 16, 4)"/></seq> <!-- Grab everything after the space for <comment> --> <comment><xsl:value-of select="substring-after(., ' ')"/></comment> </bookings> </xsl:template> <!-- Scenario 2: Input is plain text (uses XSLT 3.0's initial template) --> <xsl:template name="xsl:initial-template"> <xsl:variable name="input-text" select="'abc01223jan20212605 mytext'"/> <bookings> <name><xsl:value-of select="substring($input-text, 1, 3)"/></name> <uid><xsl:value-of select="replace(substring($input-text, 4, 3), '0', 'o')"/></uid> <date><xsl:value-of select="substring($input-text, 7, 9)"/></date> <seq><xsl:value-of select="substring($input-text, 16, 4)"/></seq> <comment><xsl:value-of select="substring-after($input-text, ' ')"/></comment> </bookings> </xsl:template> </xsl:stylesheet>
How This Works
Let's break down the substring logic to match your input abc01223jan20212605 mytext:
<name>: Takes the first 3 characters (abc)<uid>: Takes characters 4-6 (012) and replaces the leading0withoto match your example output (o12)—remove thereplace()call if you just want the raw012<date>: Takes 9 characters starting at position 7 (23jan2021)<seq>: Takes 4 characters starting at position 16 (2605)<comment>: Usessubstring-after()to capture everything after the space in your input (mytext)
Also note: I fixed the inconsistent tag casing in your target XML (you had <Date> opening and </date> closing)—XML is case-sensitive, so this ensures your output is valid.
How to Run It
- For XML input: Wrap your text in an
<input>element and run the XSLT against that XML file. - For plain text: Use an XSLT 3.0 processor (like Saxon) which will automatically execute the
xsl:initial-templateand generate the output.
内容的提问来源于stack exchange,提问作者user1481980

