XSLT: select all nodes that start with

xpath, xslt-1.0

Solution

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" encoding="UTF-8" />
  <!-- match the node that has a name starting with 'first' -->
  <xsl:template match="node()[starts-with(name(), 'first')]">
    <xsl:element name="people">
      <xsl:element name="person">
        <xsl:element name="name">
          <xsl:element name="first">
            <xsl:value-of select="." />
          </xsl:element>
          <xsl:element name="last">
            <xsl:value-of select="following-sibling::*[1]" />
          </xsl:element>
        </xsl:element>
      </xsl:element>
    </xsl:element>
    <xsl:apply-templates />
  </xsl:template>
  <!-- stop the processor walking the rest of the tree and hitting text nodes -->
  <xsl:template match="text()|@*" />
</xsl:stylesheet>

Problem

I am trying to do a XSLT transformation where the input XML is arbitrary. The only thing that's constant in it is that it'll have a node the name of which starts with 'first'. I need to get the value of that node and it's immediate sibling. However, the following template produces only the XML declaration. If it matters, this code is in Ruby using Nokogiri XML parser. However, I think this is more of a XSLT/XPath question rather than a Ruby question and hence tagging accordingly. Input XML: ``` <?xml version="1.0"?> <employees> <employee> <first_name>Winnie</first_name> <last_name>the Pooh</last_name> </employee> <employee> <first_name>Jamie</first_name> <last_name>the Weeh</last_name> </employee> </employees> ``` Desired output XML: ``` <?xml version="1.0"?> <people> <person> <first>Winnie</first> <last>the Pooh</last> </person> <person> <first>Jamie</first> <last>the Weeh</last> </person> </people> ``` XSLT: ``` <?xml version="1.0"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes" encoding="UTF-8" /> <xsl:template match="/"> <xsl:for-each select="node()[starts-with(name(), 'first')]"> <people> <person> <name> <first><xsl:value-of select="." /></first> <last><xsl:value-of select="following-sibling::*[1]" /></last> </name> </person> </people> </xsl:for-each> </xsl:template> </xsl:stylesheet> ```

Original source