Answers.Body: <p>I can show you a simple way in R, using biomaRt. Let's say you have two snp ids you want to exmine.</p>
  
  <pre><code>SNPids &lt;- c("rs431905509", "rs431905511")
  
  library("biomaRt")
  
  # To show which marts are available
  listMarts()
  
  # You need the SNP mart
  mart &lt;- useMart("ENSEMBL_MART_SNP")
  
  # Find homo sapiens
  listDatasets(mart)
  
  # This will be the dataset we want to use
  dataset &lt;- useDataset("hsapiens_snp", mart=mart)
  
  # Show available filters
  listFilters(dataset)
  
  # Now list all available attributes
  listAttributes(dataset)
  
  # To get the ensembl gene id belonging to the SNPs
  getBM(attributes=c('refsnp_id', 'ensembl_gene_stable_id'), 
        filters = 'snp_filter', 
        values = SNPids, 
        mart = dataset)
  
      refsnp_id ensembl_gene_stable_id
  1 rs431905509        ENSG00000070371
  2 rs431905509        ENSG00000100075
  3 rs431905509        ENSG00000260924
  4 rs431905511        ENSG00000145335
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-09-10T08:34:51.797Z
Answers.LastActivityDate: 2017-09-10T09:43:53.693Z
Answers.LastEditDate: 2017-09-10T09:43:53.693Z
Answers.UserDisplayName: benn
Answers.Body: <p>If you want a fast (binary) search with a locally-stored dataset, where you know exactly what SNPs and gene annotations are being queried, here's a way to set up files to do your own querying, which should scale up nicely if you have a lot of SNPs.</p>
  
  <p>1) Get annotations of interest and write them into a sorted BED file.</p>
  
  <p>For example, here's a way to get Gencode v26 gene annotations:</p>
  
  <pre><code>$ wget -qO- ftp://ftp.sanger.ac.uk/pub/gencode/Gencode_human/release_26/gencode.v26.basic.annotation.gff3.gz \
      | gunzip -c \
      | convert2bed --input=gff - \
      &gt; gencode.v26.bed
  </code></pre>
  
  <p>2) Get SNPs and write them into a text file sorted by SNP ID. </p>
  
  <p>For <code>hg38</code>, for instance:</p>
  
  <pre><code>$ LC_ALL=C
  $ wget -qO- http://hgdownload.cse.ucsc.edu/goldenpath/hg38/database/snp147.txt.gz \
     | gunzip -c \
     | awk -v OFS="\t" '{ print $5,$2,$3,($3+1) }' \
     | sort -k1,1 \
     &gt; hg38.snp147.sortedByName.txt
  </code></pre>
  
  <p>3) Install <a href="https://github.com/pts/pts-line-bisect" rel="nofollow noreferrer">pts-line-bisect</a>:</p>
  
  <pre><code>$ git clone https://github.com/pts/pts-line-bisect.git
  $ cd pts-line-bisect &amp;&amp; make &amp;&amp; cd ..
  </code></pre>
  
  <p>4) Run a query:</p>
  
  <pre><code>$ rs_of_interest=rs2814778
  $ ./pts-line-bisect/pts_lbsearch -p hg38.snp147.sortedByName.txt ${rs_of_interest} \
     | head -1 \
     | cut -f2- \
     | bedmap --echo --echo-map-id-uniq --range 1000 - gencode.v26.bed \
     &gt; answer.bed
  </code></pre>
  
  <p>The file <code>answer.bed</code> contains the genomic interval of the SNP of interest, along with the IDs of any Gencode v26 gene annotations within 1000 nt upstream and downstream of the SNP.</p>
  
  <p>To repeat step 4 within a Python script, you can use <code>subprocess.check_output()</code>:</p>
  
  <pre><code>...
  pts_lbsearch = os.path.join(project_dir, "pts-line-bisect", "pts_lbsearch")
  if not os.path.exists(pts_lbsearch):
    print "Content-type:application/json\r\n\r\n"
    print json.dumps({'error' : 'could not locate pts_lbsearch [%s]' % (pts_lbsearch)})
    sys.exit(errno.ENOENT)
  
  if term.startswith('rs'):
    query_fn = os.path.join(annotations_dir, "hg38.snp147.sortedByName.txt")
    cmd = "%s -p %s %s" % (pts_lbsearch, query_fn, term)
    try:
      res = subprocess.check_output(cmd, shell=True)
      if res and len(res) &gt; 0:
        (chr, start, stop) = res.strip().split('\n')[0].split('\t')
      else:
        pass
    except subprocess.CalledProcessError as err:
      sys.stderr.write("Query failed!\n")
      sys.exit(errno.EIO)
  
  #
  # map 'chr', 'start', and 'stop' variables to annotations with 
  # another subprocess call (not shown -- use example above)
  #
  ...
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-09-10T21:57:31.637Z
Answers.LastActivityDate: 2017-09-10T22:08:41.117Z
Answers.LastEditDate: 2017-09-10T22:08:41.117Z
Answers.UserDisplayName: Alex Reynolds
Answers.Body: <p>Have you tried using SnpEff and SnpShift (<a href="http://snpeff.sourceforge.net" rel="nofollow noreferrer">http://snpeff.sourceforge.net</a>) for annotation of the SNPs?</p>
  
  <p>Even if your desired organism available in their annotation database you can create them easily with the gene bank files. Other than annotation the tools features a bunch of other amazing functionalities.</p>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-09-18T12:15:40.003Z
Answers.LastActivityDate: 2017-09-18T12:15:40.003Z
Answers.UserDisplayName: arup
Answers.Body: <pre><code>BiocManager::install('biomaRt')
  require(biomaRt)
  ensembl &lt;- useMart(&quot;ENSEMBL_MART_SNP&quot;, dataset = &quot;hsapiens_snp&quot;)
  getBM(attributes=c(&quot;refsnp_id&quot;, &quot;chr_name&quot;, &quot;chrom_start&quot;, &quot;chrom_end&quot;,
                     &quot;allele&quot;, &quot;mapweight&quot;, &quot;validated&quot;, &quot;allele_1&quot;, &quot;minor_allele&quot;,
                     &quot;minor_allele_freq&quot;, &quot;minor_allele_count&quot;, &quot;clinical_significance&quot;,
                     &quot;synonym_name&quot;, &quot;ensembl_gene_stable_id&quot;),
        filters=&quot;snp_filter&quot;, values=c(&quot;rs6025&quot;,&quot;rs431905509&quot;),
        mart=ensembl, uniqueRows=TRUE)
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-07-20T16:38:44.867Z
Answers.LastActivityDate: 2020-07-20T16:38:44.867Z
Answers.UserDisplayName: Shicheng Guo
Answers.Body: <p>using ncbi-efetch and <strong>XSLT</strong> with the following stylesheet:</p>
  
  <pre><code>&lt;?xml version='1.0' encoding="UTF-8"?&gt;
  &lt;xsl:stylesheet
      xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
      xmlns:r="https://www.ncbi.nlm.nih.gov/SNP/docsum"
      version='1.1'
      &gt;
  &lt;xsl:output method="text"  encoding="UTF-8"/&gt;
  
  &lt;xsl:template match="/"&gt;
  &lt;xsl:apply-templates select="r:ExchangeSet"/&gt;
  &lt;/xsl:template&gt;
  &lt;xsl:template match="r:ExchangeSet"&gt;
  &lt;xsl:apply-templates select="r:Rs"/&gt;
  &lt;/xsl:template&gt;
  &lt;xsl:template match="r:Rs"&gt;
  &lt;xsl:apply-templates select="r:Assembly/r:Component/r:MapLoc/r:FxnSet"/&gt;
  &lt;/xsl:template&gt;
  
  
  &lt;xsl:template match="r:FxnSet"&gt;
  &lt;xsl:text&gt;rs&lt;/xsl:text&gt;
  &lt;xsl:value-of select="../../../../@rsId"/&gt;
  &lt;xsl:text&gt;  ncbi:&lt;/xsl:text&gt;
  &lt;xsl:value-of select="@geneId"/&gt;
  &lt;xsl:text&gt;  &lt;/xsl:text&gt;
  &lt;xsl:value-of select="@symbol"/&gt;
  &lt;xsl:text&gt;
  &lt;/xsl:text&gt;
  &lt;/xsl:template&gt;
  
  &lt;/xsl:stylesheet&gt;
  </code></pre>
  
  <p>usage (group the rs# by 3):</p>
  
  <pre><code>$ echo -e "rs8179065\nrs12899845\nrs8179066\nrs80357332\nrs80356920\n" | xargs  -L 3 echo  | tr " " "," | while read R; do curl -sL "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=snp&amp;id=${R}&amp;retmode=xml" | xsltproc --novalid  transform.xsl -; done | uniq
  rs8179065   ncbi:374654 KIF7
  rs12899845  ncbi:90381  TICRR
  rs8179066   ncbi:374654 KIF7
  rs80357332  ncbi:672    BRCA1
  rs80356920  ncbi:672    BRCA1
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-09-11T08:50:28.680Z
Answers.LastActivityDate: 2017-09-11T09:03:01.633Z
Answers.LastEditDate: 2017-09-11T09:03:01.633Z
Answers.UserDisplayName: Pierre
Answers.Body: <blockquote>
    <p>I wonder if there is a simpler solution recently? (and hopefully, I can solve it within the scope of python. )</p>
  </blockquote>
  
  <p>A <em>simpler</em> solution, I don't know... but this is at least <em>one</em> Python solution using <a href="http://biopython.org/DIST/docs/tutorial/Tutorial.html#htoc118" rel="noreferrer">Biopython's ELink method</a> via <a href="https://www.ncbi.nlm.nih.gov/books/NBK25499/" rel="noreferrer">NCBI's Entrez E-utils</a>.</p>
  
  <p>The Biopython library is flexible enough (they have an in-depth tutorial worth reading) to modify the code below to to fit project-specific needs.  For example, the mapping between snp id and gene id is lost with this bulk request method.</p>
  
  <pre><code>from Bio import Entrez
  Entrez.email = "youremail@gmail.com"
  
  snp_ids = ["rs8179065", 
             "rs12899845", 
             "rs8179066", 
             "rs80357332", 
             "rs80356920"]
  
  record = Entrez.read(Entrez.elink(dbfrom="snp", 
                                    id=",".join(snp_ids).replace('rs', ''), 
                                    db="gene"))
  </code></pre>
  
  <p>This returns a <code>record</code> object</p>
  
  <pre><code>[{'LinkSetDb': [{'DbTo': 'gene', 'LinkName': 'snp_gene', 'Link': [{'Id': '374654'}, {'Id': '90381'}, {'Id': '672'}]}], 'ERROR': [], 'LinkSetDbHistory': [], 'DbFrom': 'snp', 'IdList': ['8179065', '8179066', '12899845', '80356920', '80357332']}]
  </code></pre>
  
  <p>which contains several iterable fields -- 'Link' has a list of the Gene <strong>UID</strong>'s that can be converted to names using <code>ESummary</code>.</p>
  
  <pre><code>for gene_id in record[0]['LinkSetDb'][0]['Link']:
      handle = Entrez.esummary(db="gene", id=gene_id['Id'])
      uid_record = Entrez.read(handle)
      handle.close()
  
      uid_summary = uid_record["DocumentSummarySet"]['DocumentSummary'][0]
      print (gene_id['Id'], uid_summary['Name'])
      # ...or something more interesting than print
  
  
  374654 KIF7
  90381 TICRR
  672 BRCA1
  </code></pre>
  
  <p>An option to preserve discrete mapping, is to loop over each snp id and extract the gene(s):</p>
  
  <p><em>although I don't endorse the method below, especially for long lists of snps, you may flood the server with too many requests, maybe someone more familiar can comment on request limits or best practices for Entrez</em></p>
  
  <pre><code>for snp_id in snp_ids:
      record = Entrez.read(Entrez.elink(dbfrom="snp", 
                                    id=snp_id.replace('rs',''), 
                                    db="gene"))
      results = record[0]['LinkSetDb'][0]['Link']
      for result in results:
          uid = result['Id']
          handle = Entrez.esummary(db="gene", id=uid)
          uid_record = Entrez.read(handle)
          handle.close()
          uid_summary = uid_record["DocumentSummarySet"]['DocumentSummary'][0]
          gene_name = uid_summary['Name']
  
          print(snp_id, uid, gene_name)
  
  rs8179065 374654 KIF7
  rs12899845 374654 KIF7
  rs12899845 90381 TICRR
  rs8179066 374654 KIF7
  rs80357332 672 BRCA1
  rs80356920 672 BRCA1
  </code></pre>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-09-10T14:38:44.270Z
Answers.LastActivityDate: 2017-09-10T14:38:44.270Z
Answers.UserDisplayName: Kevin
Body: <p>Is there a way for me to get a list of genes given a list of SNP rs ids? I found several questions asked with a similar goal years ago, and the answers are always about using multiple online tools, and/or R programming. </p>
  
  <p>I wonder if there is a simpler solution recently? (and hopefully, I can solve it within the scope of python. )</p>
  
  <p>The relevant question I found (that are asked and answered more than five years ago.)</p>
  
  <ul>
  <li><a href="https://support.bioconductor.org/p/39278/" rel="noreferrer">https://support.bioconductor.org/p/39278/</a></li>
  <li><a href="https://www.biostars.org/p/10437/" rel="noreferrer">https://www.biostars.org/p/10437/</a> </li>
  <li><a href="https://www.biostars.org/p/413/" rel="noreferrer">https://www.biostars.org/p/413/</a> </li>
  </ul>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2017-10-03T06:10:44.397Z
Comments.Text: Actually functional annotation is a key step in SNP calling pipelines. I have used SnpEff and it worked perfectly. Even if you have to build your own data base given the reference genome and the gene models against the SNPs were called. I have a script if you want to use it as guide.
Comments.UserDisplayName: Erik
Tags: <database><gene><snp>
Title: How to get a list of genes corresponding to the list of SNPs (rs ids)?
ThreadText: # How to get a list of genes corresponding to the list of SNPs (rs ids)?
  
  (Asked by: username_0 on 2017-09-09)
  
  Is there a way for me to get a list of genes given a list of SNP rs ids? I found several questions asked with a similar goal years ago, and the answers are always about using multiple online tools, and/or R programming.
  
  I wonder if there is a simpler solution recently? (and hopefully, I can solve it within the scope of python. )
  
  The relevant question I found (that are asked and answered more than five years ago.)
  
  * <https://support.bioconductor.org/p/39278/>
  * <https://www.biostars.org/p/10437/>
  * <https://www.biostars.org/p/413/>
  
  **Tags:** database, gene, snp
  
  > **Comments:**
  > **username_1**: Actually functional annotation is a key step in SNP calling pipelines. I have used SnpEff and it worked perfectly. Even if you have to build your own data base given the reference genome and the gene models against the SNPs were called. I have a script if you want to use it as guide.  
  
  ---
  
  ## 6 answers
  
  ### Answer by username_7 on 2017-09-10. Score: 8 | Accepted answer
  
  > I wonder if there is a simpler solution recently? (and hopefully, I can solve it within the scope of python. )
  
  A *simpler* solution, I don't know... but this is at least *one* Python solution using [Biopython's ELink method](http://biopython.org/DIST/docs/tutorial/Tutorial.html#htoc118) via [NCBI's Entrez E-utils](https://www.ncbi.nlm.nih.gov/books/NBK25499/).
  
  The Biopython library is flexible enough (they have an in-depth tutorial worth reading) to modify the code below to to fit project-specific needs. For example, the mapping between snp id and gene id is lost with this bulk request method.
  
  ```
  from Bio import Entrez
  Entrez.email = "youremail@gmail.com"
  
  snp_ids = ["rs8179065", 
             "rs12899845", 
             "rs8179066", 
             "rs80357332", 
             "rs80356920"]
  
  record = Entrez.read(Entrez.elink(dbfrom="snp", 
                                    id=",".join(snp_ids).replace('rs', ''), 
                                    db="gene"))
  
  ```
  
  This returns a `record` object
  
  ```
  [{'LinkSetDb': [{'DbTo': 'gene', 'LinkName': 'snp_gene', 'Link': [{'Id': '374654'}, {'Id': '90381'}, {'Id': '672'}]}], 'ERROR': [], 'LinkSetDbHistory': [], 'DbFrom': 'snp', 'IdList': ['8179065', '8179066', '12899845', '80356920', '80357332']}]
  
  ```
  
  which contains several iterable fields -- 'Link' has a list of the Gene **UID**'s that can be converted to names using `ESummary`.
  
  ```
  for gene_id in record[0]['LinkSetDb'][0]['Link']:
      handle = Entrez.esummary(db="gene", id=gene_id['Id'])
      uid_record = Entrez.read(handle)
      handle.close()
  
      uid_summary = uid_record["DocumentSummarySet"]['DocumentSummary'][0]
      print (gene_id['Id'], uid_summary['Name'])
      # ...or something more interesting than print
  
  374654 KIF7
  90381 TICRR
  672 BRCA1
  
  ```
  
  An option to preserve discrete mapping, is to loop over each snp id and extract the gene(s):
  
  *although I don't endorse the method below, especially for long lists of snps, you may flood the server with too many requests, maybe someone more familiar can comment on request limits or best practices for Entrez*
  
  ```
  for snp_id in snp_ids:
      record = Entrez.read(Entrez.elink(dbfrom="snp", 
                                    id=snp_id.replace('rs',''), 
                                    db="gene"))
      results = record[0]['LinkSetDb'][0]['Link']
      for result in results:
          uid = result['Id']
          handle = Entrez.esummary(db="gene", id=uid)
          uid_record = Entrez.read(handle)
          handle.close()
          uid_summary = uid_record["DocumentSummarySet"]['DocumentSummary'][0]
          gene_name = uid_summary['Name']
  
          print(snp_id, uid, gene_name)
  
  rs8179065 374654 KIF7
  rs12899845 374654 KIF7
  rs12899845 90381 TICRR
  rs8179066 374654 KIF7
  rs80357332 672 BRCA1
  rs80356920 672 BRCA1
  
  ```
  
  
  ---
  
  ### Answer by username_2 on 2017-09-10. Score: 7
  
  I can show you a simple way in R, using biomaRt. Let's say you have two snp ids you want to exmine.
  
  ```
  SNPids <- c("rs431905509", "rs431905511")
  
  library("biomaRt")
  
  # To show which marts are available
  listMarts()
  
  # You need the SNP mart
  mart <- useMart("ENSEMBL_MART_SNP")
  
  # Find homo sapiens
  listDatasets(mart)
  
  # This will be the dataset we want to use
  dataset <- useDataset("hsapiens_snp", mart=mart)
  
  # Show available filters
  listFilters(dataset)
  
  # Now list all available attributes
  listAttributes(dataset)
  
  # To get the ensembl gene id belonging to the SNPs
  getBM(attributes=c('refsnp_id', 'ensembl_gene_stable_id'), 
        filters = 'snp_filter', 
        values = SNPids, 
        mart = dataset)
  
      refsnp_id ensembl_gene_stable_id
  1 rs431905509        ENSG00000070371
  2 rs431905509        ENSG00000100075
  3 rs431905509        ENSG00000260924
  4 rs431905511        ENSG00000145335
  
  ```
  
  
  ---
  
  ### Answer by username_3 on 2017-09-10. Score: 2
  
  If you want a fast (binary) search with a locally-stored dataset, where you know exactly what SNPs and gene annotations are being queried, here's a way to set up files to do your own querying, which should scale up nicely if you have a lot of SNPs.
  
  1) Get annotations of interest and write them into a sorted BED file.
  
  For example, here's a way to get Gencode v26 gene annotations:
  
  ```
  $ wget -qO- ftp://ftp.sanger.ac.uk/pub/gencode/Gencode_human/release_26/gencode.v26.basic.annotation.gff3.gz \
      | gunzip -c \
      | convert2bed --input=gff - \
      > gencode.v26.bed
  
  ```
  
  2) Get SNPs and write them into a text file sorted by SNP ID.
  
  For `hg38`, for instance:
  
  ```
  $ LC_ALL=C
  $ wget -qO- http://hgdownload.cse.ucsc.edu/goldenpath/hg38/database/snp147.txt.gz \
     | gunzip -c \
     | awk -v OFS="\t" '{ print $5,$2,$3,($3+1) }' \
     | sort -k1,1 \
     > hg38.snp147.sortedByName.txt
  
  ```
  
  3) Install [pts-line-bisect](https://github.com/pts/pts-line-bisect):
  
  ```
  $ git clone https://github.com/pts/pts-line-bisect.git
  $ cd pts-line-bisect && make && cd ..
  
  ```
  
  4) Run a query:
  
  ```
  $ rs_of_interest=rs2814778
  $ ./pts-line-bisect/pts_lbsearch -p hg38.snp147.sortedByName.txt ${rs_of_interest} \
     | head -1 \
     | cut -f2- \
     | bedmap --echo --echo-map-id-uniq --range 1000 - gencode.v26.bed \
     > answer.bed
  
  ```
  
  The file `answer.bed` contains the genomic interval of the SNP of interest, along with the IDs of any Gencode v26 gene annotations within 1000 nt upstream and downstream of the SNP.
  
  To repeat step 4 within a Python script, you can use `subprocess.check_output()`:
  
  ```
  ...
  pts_lbsearch = os.path.join(project_dir, "pts-line-bisect", "pts_lbsearch")
  if not os.path.exists(pts_lbsearch):
    print "Content-type:application/json\r\n\r\n"
    print json.dumps({'error' : 'could not locate pts_lbsearch [%s]' % (pts_lbsearch)})
    sys.exit(errno.ENOENT)
  
  if term.startswith('rs'):
    query_fn = os.path.join(annotations_dir, "hg38.snp147.sortedByName.txt")
    cmd = "%s -p %s %s" % (pts_lbsearch, query_fn, term)
    try:
      res = subprocess.check_output(cmd, shell=True)
      if res and len(res) > 0:
        (chr, start, stop) = res.strip().split('\n')[0].split('\t')
      else:
        pass
    except subprocess.CalledProcessError as err:
      sys.stderr.write("Query failed!\n")
      sys.exit(errno.EIO)
  
  #
  # map 'chr', 'start', and 'stop' variables to annotations with 
  # another subprocess call (not shown -- use example above)
  #
  ...
  
  ```
  
  
  ---
  
  ### Answer by username_4 on 2017-09-18. Score: 1
  
  Have you tried using SnpEff and SnpShift (<http://snpeff.sourceforge.net>) for annotation of the SNPs?
  
  Even if your desired organism available in their annotation database you can create them easily with the gene bank files. Other than annotation the tools features a bunch of other amazing functionalities.
  
  
  ---
  
  ### Answer by username_5 on 2020-07-20. Score: 0
  
  ```
  BiocManager::install('biomaRt')
  require(biomaRt)
  ensembl <- useMart("ENSEMBL_MART_SNP", dataset = "hsapiens_snp")
  getBM(attributes=c("refsnp_id", "chr_name", "chrom_start", "chrom_end",
                     "allele", "mapweight", "validated", "allele_1", "minor_allele",
                     "minor_allele_freq", "minor_allele_count", "clinical_significance",
                     "synonym_name", "ensembl_gene_stable_id"),
        filters="snp_filter", values=c("rs6025","rs431905509"),
        mart=ensembl, uniqueRows=TRUE)
  
  ```
  
  
  ---
  
  ### Answer by username_6 on 2017-09-11. Score: 0
  
  using ncbi-efetch and **XSLT** with the following stylesheet:
  
  ```
  <?xml version='1.0' encoding="UTF-8"?>
  <xsl:stylesheet
      xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
      xmlns:r="https://www.ncbi.nlm.nih.gov/SNP/docsum"
      version='1.1'
      >
  <xsl:output method="text"  encoding="UTF-8"/>
  
  <xsl:template match="/">
  <xsl:apply-templates select="r:ExchangeSet"/>
  </xsl:template>
  <xsl:template match="r:ExchangeSet">
  <xsl:apply-templates select="r:Rs"/>
  </xsl:template>
  <xsl:template match="r:Rs">
  <xsl:apply-templates select="r:Assembly/r:Component/r:MapLoc/r:FxnSet"/>
  </xsl:template>
  
  <xsl:template match="r:FxnSet">
  <xsl:text>rs</xsl:text>
  <xsl:value-of select="../../../../@rsId"/>
  <xsl:text>  ncbi:</xsl:text>
  <xsl:value-of select="@geneId"/>
  <xsl:text>  </xsl:text>
  <xsl:value-of select="@symbol"/>
  <xsl:text>
  </xsl:text>
  </xsl:template>
  
  </xsl:stylesheet>
  
  ```
  
  usage (group the rs# by 3):
  
  ```
  $ echo -e "rs8179065\nrs12899845\nrs8179066\nrs80357332\nrs80356920\n" | xargs  -L 3 echo  | tr " " "," | while read R; do curl -sL "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=snp&id=${R}&retmode=xml" | xsltproc --novalid  transform.xsl -; done | uniq
  rs8179065   ncbi:374654 KIF7
  rs12899845  ncbi:90381  TICRR
  rs8179066   ncbi:374654 KIF7
  rs80357332  ncbi:672    BRCA1
  rs80356920  ncbi:672    BRCA1
  
  ```
  
  
  ---
  
  