Luiz Borges
Luiz Borges

Reputation: 567

Find parent with single child with the same name

Suppose I have the following XML:

<root>
 <parent>
  <name>Luiz</name>
  <son><name>Luiz</name</son>
  <daugther><name>Cristina</name></daughter>
 </parent>
 <parent>
  <name>Cristina</name>
  <daugther><name>Cristina</name></daughter>
 </parent>
 <parent>
  <name>Carolina</name>
  <daugther><name>Cristina</name></daughter>
 </parent>
</root>

What XPath can I use to test a parent to see if it has only one child (elements son or daughter) which has the same name as itself. In the example above only the second parent (Cristina) would have validated the test. It is worth mentioning that I might have many other elements besides son, daughter, parent and name.

Upvotes: 0

Views: 923

Answers (1)

Dimitre Novatchev
Dimitre Novatchev

Reputation: 243579

What XPath can I use to test a parent to see if it has only one child (elements son or daughter) which has the same name as itself.

Use:

         /*/parent
               [count(*[self::daughter or self::son]) =1
              and
                name = *[self::daughter or self::son]/name
               ]

This selects all children of the top element that are named parent, have only one child element (except the name child) and the string value of their name child is the same as the string value of the name child of their other (non-name) child.

XSLT - based verification:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/">
     <xsl:copy-of select=
         "/*/parent
               [count(*[self::daughter or self::son]) =1
              and
                name = *[self::daughter or self::son]/name]
        "/>
 </xsl:template>
</xsl:stylesheet>

when this transformation is applied on the provided XML document (with numerous errors corrected to make it well-formed):

<root>
 <parent>
  <name>Luiz</name>
  <son><name>Luiz</name></son>
  <daughter><name>Cristina</name></daughter>
 </parent>
 <parent>
  <name>Cristina</name>
  <daughter><name>Cristina</name></daughter>
 </parent>
 <parent>
  <name>Carolina</name>
  <daughter><name>Cristina</name></daughter>
 </parent>
</root>

it evaluates the XPath expression and outputs all selected nodes (in this case just one):

<parent>
   <name>Cristina</name>
   <daughter>
      <name>Cristina</name>
   </daughter>
</parent>

Upvotes: 1

Related Questions