XML-ből adatok kinyerése (shell) - updated

Hozzászólások

Oké, pici haladás :)
Azt még mindig nem tudom kiválasztani, hogy melyik azonos nevű, de más tartalmú tag-re lenne szükségem, de legalább megtaláltam, hogy miért nem ment a második script...

pl.


   {xsl:template match="INSDFeature"> 

nálam


   {xsl:template match="INSDFeature"/> 

volt, azaz a tag le volt zárva...
(elöl zárójelcsere, mert lenyelte a drupal a sort...)

Basszus... :)

Viszont a fenti kérdésre/problémára ha tud valaki okosat (akár link is jó!), azt megköszönném! :)

<-------
You can't grep on dead trees.

Szia,

a megoldás így saccra nem nehéz. Szívesen segítek, ha tudok. Ehhez azonban egy megjegyzés és egy kérés tartozik.

A megjegyzés az, hogy farigcsálhatsz éppen kézzel XSL-t, de ha parancssorból kell XML-t feldolgozni, akkor helyből xmlstarlet.

A kérés pedig: ahhoz, hogy meg tudjam csinálni a "szűrő" XPath kifejezéseket meg a kimenetet, kénytelen leszel programozói szintre lefordítani a kérdést, és leírni, hogy milyen elemeket akarsz kibányászni, mit mivel akarsz összekötni, és így tovább. Kicsit nagy nekem az ugrás a "transzkript variáns" és a tag-ek neve között.

Az xmlstarlet-re egy példa:


xmlstarlet sel -T \
  -t -m /INSDSet/INSDSeq \
    -v INSDSeq_locus \
    -o ' / '\
    -v INSDSeq_definition \
    -o ' / ' \
    -v INSDSeq_organism \
    -n \
pelda.xml 

Kimenet:


WFS1 - 7466 / WFS1: Wolfram syndrome 1 (wolframin) / Homo sapiens

Az xmlstarlet persze XSL-t generál belül; ezt meg is lehet jeleníteni, ha a -T kapcsoló helyett a -C-t adjuk meg, és elhagyjuk a feldolgozandó file-t:


xmlstarlet sel -C \
  -t -m /INSDSet/INSDSeq \
    -v INSDSeq_locus \
    -o ' / '\
    -v INSDSeq_definition \
    -o ' / ' \
    -v INSDSeq_organism \
    -n

A kimenet:


<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:exslt="http://exslt.org/common"
 xmlns:math="http://exslt.org/math"
 xmlns:date="http://exslt.org/dates-and-times"
 xmlns:func="http://exslt.org/functions"
 xmlns:set="http://exslt.org/sets"
 xmlns:str="http://exslt.org/strings"
 xmlns:dyn="http://exslt.org/dynamic"
 xmlns:saxon="http://icl.com/saxon"
 xmlns:xalanredirect="org.apache.xalan.xslt.extensions.Redirect"
 xmlns:xt="http://www.jclark.com/xt"
 xmlns:libxslt="http://xmlsoft.org/XSLT/namespace"
 xmlns:test="http://xmlsoft.org/XSLT/"
 extension-element-prefixes="exslt math date func set str dyn saxon xalanredirect xt libxslt test"
 exclude-result-prefixes="math str">
<xsl:output omit-xml-declaration="yes" indent="no"/>
<xsl:param name="inputFile">-</xsl:param>
<xsl:template match="/">
  <xsl:call-template name="t1"/>
</xsl:template>
<xsl:template name="t1">
  <xsl:for-each select="/INSDSet/INSDSeq">
    <xsl:value-of select="INSDSeq_locus"/>
    <xsl:value-of select="' / '"/>
    <xsl:value-of select="INSDSeq_definition"/>
    <xsl:value-of select="' / '"/>
    <xsl:value-of select="INSDSeq_organism"/>
    <xsl:value-of select="'&#10;'"/>
  </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Aha, bambiztam még egy kicsit a példa XML-t, így megsejtettem, mit akarsz. Alkalmunk nyílik az XPath predikátumokat használni.


xmlstarlet sel -T -t -m /INSDSet/INSDSeq/INSDSeq_feature-table \
  -o 'gen=' \
  -m INSDFeature[INSDFeature_key="'gene'"]/INSDFeature_quals/INSDQualifier[INSDQualifier_name="'gene'"] \
      -v INSDQualifier_value -b \
  -o ' kromoszoma=' \
  -m INSDFeature[INSDFeature_key="'source'"]/INSDFeature_quals/INSDQualifier[INSDQualifier_name="'chromosome'"] \
      -v INSDQualifier_value -b \
  -o ' mRNA_join#=' \
  -v "count(INSDFeature[INSDFeature_key='mRNA' and INSDInterval_operator='join'])" \
  -n \
  -m "INSDFeature[INSDFeature_key='mRNA' and INSDInterval_operator='join']" \
    -o '  mRNA_join[' -v "position()"  -o ']=' -v INSDFeature_location -n -b \
pelda.xml

Itt a kimenet:


gen=WFS1 kromoszoma=4 mRNA_join#=2
  mRNA_join[1]=join(1..165,7602..7838,17244..17326,19138..19282,21348..21518,22068..22148,25192..25340,30808..33416)
  mRNA_join[2]=join(1..165,7606..7838,17244..17326,19138..19282,21348..21518,22068..22148,25192..25340,30808..33416)

Az érdemi XSLT-k:


<xsl:template match="/">
  <xsl:call-template name="t1"/>
</xsl:template>
<xsl:template name="t1">
  <xsl:for-each select="/INSDSet/INSDSeq/INSDSeq_feature-table">
    <xsl:value-of select="'gen='"/>
    <xsl:for-each select="INSDFeature[INSDFeature_key='gene']/INSDFeature_quals/INSDQualifier[INSDQualifier_name='gene']">
      <xsl:value-of select="INSDQualifier_value"/>
    </xsl:for-each>
    <xsl:value-of select="' kromoszoma='"/>
    <xsl:for-each select="INSDFeature[INSDFeature_key='source']/INSDFeature_quals/INSDQualifier[INSDQualifier_name='chromosome']">
      <xsl:value-of select="INSDQualifier_value"/>
    </xsl:for-each>
    <xsl:value-of select="' mRNA_join#='"/>
    <xsl:value-of select="count(INSDFeature[INSDFeature_key='mRNA' and INSDInterval_operator='join'])"/>
    <xsl:value-of select="'&#10;'"/>
    <xsl:for-each select="INSDFeature[INSDFeature_key='mRNA' and INSDInterval_operator='join']">
      <xsl:value-of select="'  mRNA_join['"/>
      <xsl:value-of select="position()"/>
      <xsl:value-of select="']='"/>
      <xsl:value-of select="INSDFeature_location"/>
      <xsl:value-of select="'&#10;'"/>
    </xsl:for-each>
  </xsl:for-each>
</xsl:template>

hogyan lehet megoldani, hogy a ne egy fajta tag-et listázzon, majd a következőt, hanem az infókat "struktúráljam"

Ehhez most négy dolog jut eszembe. Semmi biztos, csak tippek: (1) az xmlstarlet "sel" módjának van --indent kapcsolója, (2) az xmlstarlet-ben van "fo" mód (Formatting XML documents), (3) az XSL template-nek XPath kifejezéssel lehet megadni, a match attribútumban, hogy mire ugorjon. Például ha match="//*", akkor azt a template-et az XSL feldolgozó minden node-ra rá fogja húzni. (A sorrendre most nem emlékszem a W3C TR-ből.) (4) Te magad is megcsinálhatod kézzel, ahogy fent én is "tabuláltam" a lista elemeit.

http://xmlstar.sourceforge.net/doc/UG/xmlstarlet-ug.html

http://www.w3.org/TR/xslt#section-Processing-Model