3

I have something like the following xml (this is not actually it the dataset is FAR larger):

 <people>
<!-- People start here -->
        <person>
        <name>Sara</name>
        <age>27</age>
        </person>
 <person>
        <name>Carl</name>
        <age>25</age>
        </person>
<!-- Nick is the father -->
    <person>
        <name>Nick</name>
        <age>52</age>
        </person>
</people>

and I have written an XSL to add a line to all of the person, imagine person now has to look like:

<person>
<name>Sara</name>
<age>27</age>
<gender>female</gender>
</person>

However I still want to keep the comments but some have comments after the end node and some do not. I have tried many angles but I don't know how to check if the preceding node is a comment or not. None of the following have worked:

  • preceding-sibling::comment()[1] (if there is ever one comment it will always get this)
  • preceding-sibling::* (doesn't pick up comments)
  • preceding::* (doesn't pick up comments)

I kind of need to look at the preceding node and check if it is of type case if it is continue if not the grab the comment and spit it out. Maybe I have to work out the node position in the whole document (how?) and then check the preceding node that way? It is not necessary for this to be efficient.

Thanks

Sara
  • 612
  • 5
  • 21
  • With thanks to James ([http://stackoverflow.com/users/27206/james-gregory](http://stackoverflow.com/users/27206/james-gregory)) for finding this. http://stackoverflow.com/questions/2991141/xslt-xpath-match-directly-preceding-comments/2991403#2991403 Works perfectly :) Thanks all! – Sara Nov 29 '12 at 13:09
  • Sara, the best solution is overriding the identity template -- exactly what thesimm is proposing. You'll benefit a lot in mastering of XSLT if you read about the identity rule and use it everywhere (where possible). This is one of the most fundamental XSLT design patterns. More about this design patter here: http://www.dpawson.co.uk/xsl/sect2/identity.html . In summary, I recommend that you accept the answer by @thesimm – Dimitre Novatchev Nov 29 '12 at 13:17

3 Answers3

2

How about something like this which preserves the comments in your xml fragment:

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="person">
    <xsl:copy>
        <xsl:copy-of select="."/>
        <gender>gender goes here</gender>
    </xsl:copy>
</xsl:template>
thesimm
  • 774
  • 3
  • 12
0

This template should copy across all processing instructions, including comments

<xsl:template match="processing-instruction()">
    <xsl:copy/>
</xsl:template>
holytshirt
  • 216
  • 2
  • 3
-1

Haven't done XSLT stuff in a while, but can you just do?

<xsl:if test="preceding-sibling::comment()[1]">
  <comment>
    <xsl:value-of select="preceding-sibling::comment()[1]" />
  </comment>
</xsl:if>

Seems to kind of work on http://www.xsltcake.com/ but gets the People comment twice.

Sarkie
  • 272
  • 3
  • 18