Home > Software engineering >  "URI has an authority component" when resolving URI
"URI has an authority component" when resolving URI

Time:07-08

I am getting the "URI has an authority component" error when trying to create a document during an XSLT transformation on a network location.

The transformation works fine locally on my pc.

My original template was:

<xsl:template match="map">
        <xsl:variable name="model" select="translate(@product,' ','')"/>
        <xsl:variable name="documentType" select="lower-case(@platform)"/>
        <xsl:variable name="locale" select="lower-case(translate(@audience,'-','_'))"/>
        <xsl:variable name="directory"><xsl:value-of select="substring-before(base-uri(/),'/toc.ditamap')"/></xsl:variable>
        <xsl:variable name="bookName" select="concat($documentType,'_',$model,'_info_',$locale,'.xml')"/>
        
        <xsl:result-document href="{$directory}/{$bookName}">
            <info>
                <xsl:for-each select="//topicref">
                    <xsl:variable name="topicFileName" select="@href"/>
                    <xsl:call-template name="enterMetadata">
                        <xsl:with-param name="topicFileName" select="$directory/$topicFileName"/>
                    </xsl:call-template>
                </xsl:for-each>
            </info>
        </xsl:result-document>
    </xsl:template>

But the URI in xsl:result-document was (wrongly) resolved as follows:

file:/C:/[somepath]/DITA/Operator Manual/om_CSUV_info_en_us.xml

So I changed the template to this (I am aware that string substitutions are not a good approach, but I am trying to get at least some output):

<xsl:template match="map">
        <xsl:variable name="model" select="translate(@product,' ','')"/>
        <xsl:variable name="documentType" select="lower-case(@platform)"/>
        <xsl:variable name="locale" select="lower-case(translate(@audience,'-','_'))"/>
        <xsl:variable name="directory"><xsl:value-of select="substring-before(replace(base-uri(/),'file:/C:/','file:/'),'/toc.ditamap')"/></xsl:variable>
        <xsl:variable name="bookName" select="concat($documentType,'_',$model,'_info_',$locale,'.xml')"/>
        
        <xsl:result-document href="{$directory}/{$bookName}">
            <info>
                <xsl:for-each select="//topicref">
                    <xsl:variable name="topicFileName" select="@href"/>
                    <xsl:call-template name="enterMetadata">
                        <xsl:with-param name="topicFileName" select="$directory/$topicFileName"/>
                    </xsl:call-template>
                </xsl:for-each>
            </info>
        </xsl:result-document>
    </xsl:template>

Now I am getting the following error:

Error in xsl:result-document/@href on line 30 column 62 of metadata.xsl:

  Cannot write to URI

  file://[somepath]/Publishing/DITA/Operator Manual/om_CSUV_info_en_us.xml (URI has an authority component)


  in built-in template rule


Cannot write to URI file://[somepath]/Publishing/DITA/Operator Manual/om_CSUV_info_en_us.xml (URI has an authority component)

This same problem was debated at length here https://saxonica.plan.io/issues/4280, but it is still not clear to me what to do to get it working. I am not a programmer, I just write XSLT scripts.

I am using Saxon HE 9.7 .Net.

CodePudding user response:

If you want to write to a network location which is already mapped to a path on your local file system you should probably use a file: URI with an explicitly empty authority component, e.g. file:///c:/blah/blah/blah.xml

CodePudding user response:

When you talk of a "network location", does that mean you are using a UNC filename such as //server/path? There's a long-standing problem that there's no consensus on how such filenames should be represented as URIs, and in particular, Java and .NET do it differently. Because Saxon 9.x on .NET involves both Java code and .NET code, it becomes particularly problematic.

The Wikipedia article on the file URI scheme sums up the muddle quite well:

There are two ways that Windows UNC filenames (such as \server\folder\data.xml) can be represented. These are both described in RFC 8089, Appendix E as "non-standard". The first way (called here the 2-slash format) is to represent the server name using the Authority part of the URI, which then becomes file://server/folder/data.xml. The second way (called here the 4-slash format) is to represent the server name as part of the Path component, so the URI becomes file:////server/folder/data.xml. Both forms are actively used. Microsoft .NET (for example, the method new Uri(path)) generally uses the 2-slash form; Java (for example, the method new URI(path)) generally uses the 4-slash form. Either form allows the most common operations on URIs (resolving relative URIs, and dereferencing to obtain a connection to the remote file) to be used successfully. However, because these URIs are non-standard, some less common operations fail: an example is the normalize operation (defined in RFC 3986 and implemented in the Java java.net.URI.normalize() method) which reduces file:////server/folder/data.xml to the unusable form file:/server/folder/data.xml.[5]

  • Related