0

I'm quite new to XSLT and I'm using XSLT 1.0. Now I need to group some stuff in a quite big XML file. There are lots of examples out there but none worked for me for some reason. I'm able to group the info I want, but I also get some extra text in my output xml. Here's what I'm doing right now;

Input XML (this is a temp XML, actual input is quite bigger but I will be able to apply the same to my real xml too)

<?xml version="1.0" encoding="utf-8"?>
<objects>
  <groupNumber>15</groupNumber>
  <object>
    <items>
      <item>
        <itemOptions>
          <itemNumber>1</itemNumber>
        </itemOptions>
      </item>
      <item>
        <itemOptions>
          <itemNumber>1</itemNumber>
        </itemOptions>
      </item>
      <item>
        <itemOptions>
          <itemNumber>2</itemNumber>
        </itemOptions>
      </item>
      <item>
        <itemOptions>
          <itemNumber>3</itemNumber>
        </itemOptions>
      </item>
      <item>
        <itemOptions>
          <itemNumber>3</itemNumber>
        </itemOptions>
      </item>
    </items>
  </object>
</objects>

Now I want to group the items by their itemNumbers. Here's what I do;

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:xs="http://www.w3.org/2001/XMLSchema"
                exclude-result-prefixes="xs xsi xsl">

  <xsl:output method="xml" encoding="UTF-8" indent="yes"/>

  <xsl:key name="itemler" match="item" use="itemOptions/itemNumber" />

  <xsl:template match="items" name="temp">
    <numbers>
    <xsl:for-each select="item[count(. | key('itemler', itemOptions/itemNumber)[1])=1]">
      <number>
        <xsl:value-of select="itemOptions/itemNumber" />
      </number>
    </xsl:for-each>
    </numbers>
  </xsl:template>
</xsl:stylesheet>

With this code, I'm getting this output;

<?xml version="1.0" encoding="utf-8"?>
15

<numbers>
  <number>1</number>
  <number>2</number>
  <number>3</number>
</numbers>

Which is almost exactly what I want, except the "15". I get the grouped numbers AND a value from tag which is under root.

I'm getting this exactly same error when I try to apply this XSLT to my main XML, I get what I want with lots of unwanted info from tags under root and some other tags. What is the problem here?

I'm guessing it's something related to templates or matches but I really have no idea how to solve.

Thank you very much.

user1767833
  • 129
  • 2
  • 10
  • The problem is that your template is applied to `items` and you have nothing else defined for other nodes. See [this](http://stackoverflow.com/a/3378562/314291) on how to debug. – StuartLC Jun 17 '14 at 12:44

1 Answers1

1

Add a template doing

<xsl:template match="/">
  <xsl:apply-templates select="//items"/>
</xsl:template>

to ensure you process only the items elements.

Martin Honnen
  • 160,499
  • 6
  • 90
  • 110
  • Thank you very much, that did the trick. I have one more question if you don't mind, lets assume I have an xslt with lost of templates, will this bring any trouble? I just tested it like that and there wasn't any problems, I'm just asking to make sure there won't be any. – user1767833 Jun 17 '14 at 12:50
  • The normal processing starts at the root node `/` and then your own templates and/or the built-in templates keep up processing. If you only want to process the `items` elements and its descendants then my suggestion is fine, if you want to process ancestors or sibling of `items` to some extent then my suggestion might not be suitable. There are however other approaches, like doing ``, to make sure that element's content is not processed. – Martin Honnen Jun 17 '14 at 13:05
  • @user1767833 It's *usually* much better to have many templates than many *for-each* blocks nested many levels deep. – helderdarocha Jun 17 '14 at 13:06