0
votes

I have been trying to solve one problem in XSLT, which is reaching the child node of a particular parent node, regardless of it is order in that parent.

lets imagine that we have an xml file:

<book>
   <id>
      <type>
           <name name="something">
              --SomeText
           </name>
      </type>
    <id>
</book>
<book>
   <name name="something">

   <name>
   <id>
      --SomeNodes--
   </id>
   <number>
   </number>
</book>

The idea here is that I have many of these node set and each of them have different order of the <name> node.

What I want is, regardless of this order, each time I match with book node, I should be able to get the value of <name> node.

XSLT:

<xsl:template match="book">

 <xsl:param name="rule" select="//name[1]>
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
   <xsl:if test=name/@name>
       <xsl:comment><xsl:value-of select="concat('some text', substring($rule,2,4))"/>
   </xsl:if>
</xsl:template>

So, with this approach obviously I get the all results of node because of "//".

If I change it to name[1] without "//" then, It only finds the first name element right after the book, but not the others.

How to get recursively each time when I match with and exact same node value and write it's value as a comment after the template.

NOTE: I give you the example as XML but I am transforming from XSLT-XSLT.

2
It would make our lives easier if your input XML were well-formed. This isn't a frivolous comment: I actually don't know where the end tags in your input are supposed to be.Michael Kay
I got succesful when I match with <name> node, but I want to do it through <book> node. So I think <xsl:key> also can be helpful, I tried a bit but no success.Sojimanatsu

2 Answers

1
votes

I think that when you're doing any kind of transformation on untidy data like this, it's best to do it as a 2-pass process: first tidy the data, then convert it to the form you want it. That way the process of tidying the data is reusable and separate.

You've only given a sketch of the input format, but I would start by transforming book elements so the name is always a top-level child:

<xsl:template match="book">
  <xsl:copy>
    <name><xsl:value-of select=".//name"/></name>
    etc.
  </xsl:copy>
</xsl:template>

Once you've tidied the data, the next step is fairly trivial.

0
votes

Instead of matching the template with <book>, you can try matching it with <name>.

<xsl:template match="name">
    <book>
        <xsl:copy>
            <xsl:apply-templates select="@name" />
        </xsl:copy>
    </book>
</xsl:template>

Output

<book>
    <name>something</name>
</book>
<book>
    <name>something</name>
</book>