简体   繁体   中英

XSLT 2.0 to 1.0

Lots of help here to convert XSLT 1.0 to 2.0, but I need to go the other way!

OK, I have an XSL file working in XSLT 2.0: I need to convert this file to XSLT 1.0. Right now, I know the transformation is getting hung up on "result-document" but I'm not sure how to fix this. And, I'm not sure if my other info will translate to 1.0: will my value-of select= statements still work? help! (thanks)!

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
    <xsl:result-document href="output.xml" method="xml">
        <playlist>
            <xsl:for-each select="//dict[preceding-sibling::*[1]='Tracks']/dict">
                <Track>
                    <Artist>
                        <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Artist']"/>
                    </Artist>
                    <Album>
                        <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Album']"/>
                    </Album>
                    <Songname>
                        <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Name']"/>
                    </Songname>
                    <TrackID>
                        <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Track ID']"/>
                    </TrackID>
                    <TagID>
                        <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Tag ID']"/>
                    </TagID>
                </Track>
            </xsl:for-each>

            <xsl:for-each select="//dict[preceding-sibling::*[1]='Upload Information']">
                <Description>
                    <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Playlist Description']"/>
                </Description>
                <Title>
                    <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Playlist Title']"/>
                </Title>
                <Username>
                    <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Username']"/>
                </Username>
                <Token>
                    <xsl:value-of select="child::*[preceding-sibling::*[1] = 'Token']"/>
                </Token>
            </xsl:for-each>
        </playlist>
    </xsl:result-document>
</xsl:template>

Well considering that result-document is new in XSLT 2.0 and that XSLT 1.0 without processor specific extension does not allow creating of multiple result documents at all it is in general not possible to translate stylesheets making use of result-document to XSLT 1.0.

However in your snippet the result-document instruction is inside the template matching the single / document node so you could simply remove it and use

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
        <playlist>
            <xsl:for-each select="//dict[preceding-sibling::*[1]='Tracks']/dict">
                <Track>
                    <Artist>
                        <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Artist']"/>
                    </Artist>
                    <Album>
                        <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Album']"/>
                    </Album>
                    <Songname>
                        <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Name']"/>
                    </Songname>
                    <TrackID>
                        <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Track ID']"/>
                    </TrackID>
                    <TagID>
                        <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Tag ID']"/>
                    </TagID>
                </Track>
            </xsl:for-each>

            <xsl:for-each select="//dict[preceding-sibling::*[1]='Upload Information']">
                <Description>
                    <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Playlist Description']"/>
                </Description>
                <Title>
                    <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Playlist Title']"/>
                </Title>
                <Username>
                    <xsl:value-of select="*[preceding-sibling::*[1][local-name()='key'] = 'Username']"/>
                </Username>
                <Token>
                    <xsl:value-of select="child::*[preceding-sibling::*[1] = 'Token']"/>
                </Token>
            </xsl:for-each>
        </playlist>

</xsl:template>

Of course you would then need to ensure you run your XSLT processor with the right arguments to write its result to output.xml .

As for value-of , check whether any of the used expressions selects multiple nodes in your input XML documents. But you only need to check if the stylesheet had once version="2.0" and was run that way with an XSLT 2.0 processor. Your posted snippet has version="1.0" , that way even an XSLT 2.0 processor would run it in backwards compatible mode where value-of semantics (output string value of first selected node) is used.

So the value-of only need adaption if with version="2.0" they output multiple values and you want to preserve that with version="1.0". You need to use for-each then eg by replacing

                    <xsl:value-of select="child::*[preceding-sibling::*[1] = 'Token']"/>

with

  <xsl:for-each select="child::*[preceding-sibling::*[1] = 'Token']">
    <xsl:if test="position() > 1"><xsl:text> </xsl:text></xsl:if>
    <xsl:value-of select="."/>
  </xsl:for-each>

The only problem with your code with xslt-1.0 would be the <xsl:result-document href="output.xml" method="xml"> . This is not supported for xslt-1.0

One possible solution could be to remove this (xsl:result-document) and redirect the "stdout" output to a file. This depends on the tools you are using.

Also some xlst processor support some extensions. For example wiht xsltproc you can replace xsl:result-document with xsl:document.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM