1

Using something similar to the answer found in this question I put together a function based off to create an XML result tree fragment that I loaded into a variable.

I was able to convert this XML

  <Summary> &lt;Summary&gt;&#xD;
        &lt;Category&gt;&#xD;
            &lt;Category&gt;Tuition and Fees&lt;/Category&gt;&#xD;
            &lt;TotalDebits&gt;0.00&lt;/TotalDebits&gt;&#xD;
            &lt;TotalCredits&gt;-3509.45&lt;/TotalCredits&gt;&#xD;
        &lt;/Category&gt;&#xD;
        &lt;Category&gt;&#xD;
            &lt;Category&gt;Miscellaneous&lt;/Category&gt;&#xD;
            &lt;TotalDebits&gt;60.62&lt;/TotalDebits&gt;&#xD;
            &lt;TotalCredits&gt;-234.36&lt;/TotalCredits&gt;&#xD;
        &lt;/Category&gt;&#xD;
    &lt;/Summary&gt;&#xD;
  </Summary>

to this

<Summary>
    <Category>
        <Category>Tuition and Fees</Category>
        <TotalDebits>0.00</TotalDebits>
        <TotalCredits>-3509.45</TotalCredits>
    </Category>
    <Category>
        <Category>Miscellaneous</Category>
        <TotalDebits>60.62</TotalDebits>
        <TotalCredits>-234.36</TotalCredits>
    </Category>
</Summary>

which is contained in this variable

  <xsl:variable name="SummaryItems">
    <xsl:call-template name="TheGreatUnescape">
      <xsl:with-param name="escaped" select="string(//Summary)" />
    </xsl:call-template>
  </xsl:variable>

Now my issue is that I'm trying to use exslt:node-set() to gain access to the nodes within this variable but I'm not getting any information.

When using a function like

<xsl:for-each select="exslt:node-set($SummaryItems)/Summary/Category">

it produces no result.

I did include the xmlns:exslt="http://exslt.org/common" declaration in the xsl:stylesheet and I've tested the node-set function so I know it works just not with the converted XML in the variable.

Have I created a real result tree fragment using that code that exslt:node-set can access?

Community
  • 1
  • 1
Matthew Green
  • 10,161
  • 4
  • 36
  • 54
  • 2
    Please, *edit* the question and provide a complete (but short) code example: 1) The XML document; 2) The transformation. 3) The result you are getting when 2) is perforemed on 1); 4) The wanted result. 5) The XSLT processor you are using. Without this information, people can only make guesses -- please, save everyone's time. – Dimitre Novatchev Jan 18 '13 at 22:01
  • @DimitreNovatchev I've tried adding more information without just putting the whole large code in this question. I think I've identified the issue is with the function not creating a real result tree fragment that I can access. I have a rather hacky way of unparsing my XMl that seems to be doing the trick but I'm still curious as to why the original function didn't work the way I expected. – Matthew Green Jan 18 '13 at 23:07
  • Mathew, `xxx:node-set()` is useful to convert an RTF to a regular node-set. However, in the described case this RTF contains just a single text node -- not of a node-set. Please, remember, that a string (even if representing XML) is not an xml node/document/fragment. The string you have in that variable needs to be parsed by an XML parser, in order to become real markup. – Dimitre Novatchev Jan 18 '13 at 23:11
  • 1
    @MatthewGreen You still haven't shown any information that would allow anyone to answer your question, you should be able to post a _complete_ stylesheet that takes a file with your quoted summary input and produces nothing, has a definition for TheGreatUnescape and then has some code using given that it should be fairly easy to say how to fix the code. – David Carlisle Jan 18 '13 at 23:13
  • Could you at least show us the content of your ``? – JLRishe Jan 19 '13 at 06:04
  • I tried the XSLT provided in the answer to the question in that link you provided, using an MSXSLT processor. I was able to access the nodes of the parsed XSLT using `msxsl:node-set()`, but the parsing logic had parsed the input incorrectly to `60.62-234.36` Perhaps that's why you can't get it to work? Maybe that's happening because the parsing logic can't handle nested elements with the same name. – JLRishe Jan 19 '13 at 06:41
  • @JLRishe That seems have been part of my issue. I tried making a change to that and it just seemed to make things worse. I had to completely reapproach how I was building the variable and I think I have it working for now. – Matthew Green Jan 21 '13 at 14:40

2 Answers2

4

The most common reason for things not matching is that they are not in the namespace that you expect, it is hard to say as you haven't shown full code but work in stages

You say

<xsl:copy-of select="exslt:node-set($SummaryItems)"/>

works, so try

<xsl:copy-of select="exslt:node-set($SummaryItems)/*"/>

If that works try

<xsl:copy-of select="exslt:node-set($SummaryItems)/Summary"/>

If that does not work then Summary is not selecting <Summary> which in 99 times out of 100 is a namespace issue.


Original answer (fixed in question)

<xsl:for-each select="exslt:node-set($SummaryItems)\Summary\Category">

should give an XPath syntax error wrong path separator

<xsl:for-each select="exslt:node-set($SummaryItems)/Summary/Category">
David Carlisle
  • 5,582
  • 1
  • 19
  • 23
  • I'm not very familiar with namespaces so could you explain that a little more? Do I need a namespace for the result tree fragment? – Matthew Green Jan 18 '13 at 22:09
  • You don't _need_ a namespace but the namespace is part of the name so an XPath of `/Summary` queries for Summary in no namespace but if there was a default namespace (`xmlns="foo"` in force when the variable was constructed and the variable contains Summary in namespace foo then it doesn't match. (and you need xmlns:f="foo" in your stylesheet an an XPath of /f:Summary but since you haven't shown how the variable is declared it's all staring at crystal balls. – David Carlisle Jan 18 '13 at 22:23
  • I updated the question with a little more information. I have a comment on the question that explains some of my recent thoughts on the issue. – Matthew Green Jan 18 '13 at 23:09
  • It seems that function did create some issues for me so I did have to redo how I was creating that variable. Thanks for the help. – Matthew Green Jan 21 '13 at 14:38
2

David Carlisle is right that namespace issues are probably the most common cause of things not matching as expected.

A second common source of problems with node sets (at least, it happens to me regularly) is temporary confusion about which nodes are denoted by the variable name bound to the node set. Details will vary with exactly how the binding is done, but from what you say it seems likely that $SummaryItems is bound to a Summary element containing two Category elements (etc.) -- if so, then the expression exslt:node-set($SummaryItems)/Summary/Category will produce no result because $SummaryItems does not contain a Summary element. The Summary elements you want are not children of the nodes in $SummaryItems -- they are the nodes in $SummaryItems.

In this case, I'd try exslt:node-set($SummaryItems)/Category.

In the more general case, when I have troubles like this I run test code to find out where I am: what does name(exslt:node-set($SummaryItems)[1]) return, for example?

C. M. Sperberg-McQueen
  • 24,596
  • 5
  • 38
  • 65