Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 3336692
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 18, 20262026-05-18T00:09:57+00:00 2026-05-18T00:09:57+00:00

I’m adapting an XSLT from a third party which transforms an arbitrary number of

  • 0

I’m adapting an XSLT from a third party which transforms an arbitrary number of XMLs into a single HTML document. It’s a pretty complex script and it will be revised in the future, so I’m trying to do a minimal adaptation in order to get it to work for our needs.

The following is a stripped down version of the XSLT (containing the essentials):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
    <xsl:output method="text" encoding="UTF-8" omit-xml-declaration="yes"/> 
    <xsl:param name="files" select="document('files.xml')//File"/>
    <xsl:param name="root" select="document($files)"/>
    <xsl:template match="/">
        <xsl:for-each select="$root/RootNode">
            <xsl:apply-templates select="."/>
        </xsl:for-each>
    </xsl:template> 
    <xsl:template match="RootNode">
        <xsl:for-each select="//Node">
            <xsl:text>Node: </xsl:text><xsl:value-of select="."/><xsl:text>, </xsl:text>
        </xsl:for-each>
    </xsl:template> 
</xsl:stylesheet>

Now files.xml contains a list of all the URLs of the files to be included (in this case the local files file1.xml and file2.xml). Because we want to read XMLs from memory rather than from disk, and because the invocation of the XSLT only allows for a single XML source, I have combined the two files in a single XML document. The following is a combination of two files (there may be more in a real situation)

<?xml version="1.0" encoding="UTF-8"?>
<TempNode>
    <RootNode>
        <Node>1</Node>
        <Node>2</Node>
    </RootNode> 
    <RootNode>
        <Node>3</Node>
        <Node>4</Node>  
    </RootNode>
</TempNode>

where the first RootNode originally resided in file1.xml and the second in file2.xml.
Due to the complexity of the actual XSLT, I’ve figured that my best shot is to try to alter the $root-param. I’ve tried the following:

<xsl:param name="root" select="/TempNode"/>

The problem is this. In the case of <xsl:param name="root" select="document($files)"/>, the XPath expression "//Node" in <xsl:for-each select="//Node"> selects the Node’s from file1.xml and file2.xml independently, i.e. producing the following (desired) list:

Node: 1, Node: 2, Node: 3, Node: 4,

However, when I combine the content of the two files into a single XML and parse this (and use the suggested $root-definition), the expression "//Node" will select all Node’s that are children of the TempNode. (In other words, the desired list, as represented above, is produced twice due to the combination with the outer <xsl:for-each select="$root/RootNode"> loop.)

(A side note: as observed in comment a) in this page, document() apparently changes the root node, perhaps explaining this behavior.)

My question becomes:
How can I re-define $root, using the combined XML as source instead of a multi-source through document(), so that the list is only produced once, without touching the remainder of the XSLT? It’s like if $root defined using the document()-function, there is no common root node in the param. Is it possible to define a param with two “separate” node trees?

Btw: I’ve tried defining a document like this

<xsl:param name="root">
    <xsl:for-each select="/TempNode/*">
        <xsl:document>
            <xsl:copy-of select="."/>
        </xsl:document>
    </xsl:for-each>
</xsl:param>

thinking it might solve the problem, but the "//Node" expression still fetches all the Nodes. Is the context node in the <xsl:template match="RootNode">-template actually somewhere in the input document and not the param? (Honestly, I’m pretty confused when it comes to context nodes.)

Thanks in advance!

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-18T00:09:57+00:00Added an answer on May 18, 2026 at 12:09 am

    (Updated more)

    OK, some of the problem is becoming clear. First, just to make sure I understand, you aren’t actually passing parameters for $files and $root to the XSLT processor invocation, right? (They might as well be variables rather than params?)

    Now to the main issues… In XPath, when you evaluate an expression that begins with “/” (including “//”), the context node is ignored [mostly]. Therefore, when you have

    <xsl:template match="RootNode">
        <xsl:for-each select="//Node">
    

    the matched RootNode is ignored. Maybe you wanted

    <xsl:template match="RootNode">
        <xsl:for-each select=".//Node">
    

    in which the for-each would select Node elements that are descendants of the matched RootNode? This would fix your problem of generating the desired node list twice.

    I inserted [mostly] above because I recalled that an “absolute location path” starts from “the root node of the document containing the context node”. So the context node does affect what document is used for “//Node”. Maybe that’s what you intended all along? I guess I was slow to catch on to that.

    (A side note: as observed in comment
    a) in this page, document() apparently
    changes the root node, perhaps
    explaining this behavior.)

    Or more precisely,

    An absolute location path [“/…”]
    followed by a relative location
    path… selects the set of nodes that
    would be selected by the relative
    location path relative to the root
    node of the document containing the
    context node
    .

    document() doesn’t actually change anything, in the sense of side effects; rather, it returns a set of nodes contained (usually) by different documents than the primary source document. XSLT instructions like xsl:apply-templates and xsl:for-each establish new values for the context node inside the scope of their template bodies. So if you use xsl:apply-templates and xsl:for-each with select=”document(…)/…”, the context node inside the scope of those instructions will belong to an external document, so any use of “/…” as an XPath will start from that external document.

    Updated again

    How can I re-define $root, using the
    combined XML as source instead of a
    multi-source through document(), so
    that the list is only produced once,
    without touching the remainder of the
    XSLT?

    As @Alej hinted, it’s really not possible given the above constraint. If you’re selecting “//Node” in each iteration of the loop over “$root/RootNode”, then in order for each iteration not to select the same nodes as the other iterations, each value of “$root/RootNode” must be in a different document. Since you’re using the combined XML source, instead of a multi-source, this is not possible.

    But if you don’t insist that your <xsl:for-each select="//..."> XPath expression cannot change, it becomes very easy. 🙂 Just put a “.” before the “//”.

    It’s like if $root defined using the document()-function, there is no common root node
    in the param.

    The value of the param is a node-set. All nodes in the set may be contained in the same document, or they may not, depending on whether the first argument to document() is a nodeset or just a single node.

    Is it possible to define a param with two “separate” node trees?

    I believe by “separate”, you mean “belonging to different documents”? Yes it is, but I don’t think you can do it in XSLT 1.0 unless you’re selecting nodes that belong to different documents in the first place.

    You mentioned trying

    <xsl:param name="root">
        <xsl:for-each select="/TempNode/*">
            <xsl:document>
                <xsl:copy-of select="."/>
            </xsl:document>
        </xsl:for-each>
    </xsl:param>
    

    but <xsl:document> is not defined in XSLT 1.0, and your stylesheet says version=”1.0″. Do you have XSLT 2.0 available? If so, let us know and we can pursue this option. To be honest, <xsl:document> is not familiar territory for me. But I’m happy to learn along with you.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I have a bunch of posts stored in text files formatted in yaml/textile (from
We're building an app, our first using Rails 3, and we're having to build
I have this code: - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock { NSString *someString = [[NSString
I am trying to loop through a bunch of documents I have to put
I'm making a simple page using Google Maps API 3. My first. One marker
I have some data like this: 1 2 3 4 5 9 2 6

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.