Search code examples
xmlxsltxslt-2.0

XSLT call only immediate any occurence of child nodes


I have two possible input XMLs as below. I am looking to get only the parents account information and ignore the account under <line>.

Tried using //account and .//account, both return all the account segments, so respective count is 2 and 4 for each xml. expecting count is 1 and 2 <account>

xml1:

<?xml version="1.0" encoding="UTF-8"?>
<inventory>
  <account>
    <seg1>123</seg1>
    <seg2>qwe</seg2>
  </account>
  <line>
    <account>
      <seg1>123</seg1>
      <seg2>qwe</seg2>
    </account>
  </line>
</inventory>

xml2:

<?xml version="1.0" encoding="UTF-8"?>
<inventory>
  <accounts>
    <account>
        <seg1>123</seg1>
        <seg2>qwe</seg2>
    </account>
    <account>
        <seg1>456</seg1>
        <seg2>abc</seg2>
    </account>
</accounts>
  <line>
    <accounts>
        <account>
            <seg1>123</seg1>
            <seg2>qwe</seg2>
        </account>
        <account>
            <seg1>456</seg1>
            <seg2>abc</seg2>
        </account>
    </accounts>
 </line>
</inventory>

So I am expecting to read only immediate account information and ignore account under <line> segment


Solution

  • to satisfy both xml 1 and 2, use

    [not(ancestor-or-self::line)]
    

    here's the xslt

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
    
        <xsl:template match="/">
            <inventory>
                <xsl:copy-of select="//*[not(ancestor-or-self::line)]/account"/>       
            </inventory>
        </xsl:template>
    </xsl:stylesheet>