2016-12-03 79 views
2

我想按照这个层次的格式为:MeSH Qualifier Hierarchies创建一个层次树

输入XML

<QualifierRecordSet LanguageCode="eng"> 
    <QualifierRecord> 
    <String>chemistry</String> 
    <TreeNumber>Y03</TreeNumber> 
    </QualifierRecord> 
    <QualifierRecord> 
    <String>agonists</String> 
    <TreeNumber>Y03.010</TreeNumber> 
    <TreeNumber>Y07.030</TreeNumber> 
    </QualifierRecord> 
    <QualifierRecord> 
    <String>analogs &amp; derivatives</String> 
    <TreeNumber>Y03.020</TreeNumber> 
    </QualifierRecord> 
    <QualifierRecord> 
    <String>antagonists &amp; inhibitors</String> 
    <TreeNumber>Y03.030</TreeNumber> 
    <TreeNumber>Y07.040</TreeNumber> 
    </QualifierRecord> 
    <QualifierRecord> 
    <String>chemical synthesis</String> 
    <TreeNumber>Y03.040</TreeNumber> 
    </QualifierRecord> 
    <QualifierRecord> 
    <String>pharmacology</String> 
    <TreeNumber>Y07</TreeNumber> 
    </QualifierRecord> 
    <QualifierRecord> 
    <String>poisoning</String> 
    <TreeNumber>Y07.020.010</TreeNumber> 
    <TreeNumber>Y10.040</TreeNumber> 
    </QualifierRecord> 
    <QualifierRecord> 
    <String>pharmacokinetics</String> 
    <TreeNumber>Y07.070</TreeNumber> 
    <TreeNumber>Y08.040.060</TreeNumber> 
    </QualifierRecord> 
    <QualifierRecord> 
    <String>toxicity</String> 
    <TreeNumber>Y07.020.020</TreeNumber> 
    </QualifierRecord> 
    <QualifierRecord> 
    <String>contraindications</String> 
    <TreeNumber>Y07.050</TreeNumber> 
    <TreeNumber>Y10.030</TreeNumber> 
    </QualifierRecord> 
    <QualifierRecord> 
    <String>administration &amp; dosage</String> 
    <TreeNumber>Y07.010</TreeNumber> 
    <TreeNumber>Y10.010</TreeNumber> 
    </QualifierRecord> 
    <QualifierRecord> 
    <String>adverse effects</String> 
    <TreeNumber>Y07.020</TreeNumber> 
    <TreeNumber>Y10.020</TreeNumber> 
    </QualifierRecord> 
</QualifierRecordSet> 

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:key name="child" match="QualifierRecord" use="substring(TreeNumber, 1, string-length(TreeNumber) - 4)" /> 

<xsl:template match="QualifierRecordSet"> 
    <node id="MeSH" label="NIH MeSH Qualifiers"> 
     <isComposedBy> 
      <xsl:apply-templates select="QualifierRecord[not(contains(TreeNumber, '.'))]"/> 
     </isComposedBy> 
    </node> 
</xsl:template> 

<xsl:template match="QualifierRecord"> 
    <node id="{TreeNumber}" label="{String}"> 
     <xsl:variable name="children" select="key('child', TreeNumber)" /> 
     <xsl:if test="$children"> 
      <isComposedBy> 
       <xsl:apply-templates select="$children"/> 
      </isComposedBy> 
     </xsl:if> 
    </node> 
</xsl:template> 
</xsl:stylesheet> 

我的目标输出应该看起来像这个:

<node id="MeSH" label="NIH MeSH Qualifiers"> 
    <isComposedBy> 
    <node id="Y03" label="chemistry"> 
     <isComposedBy> 
      <node id="Y03.020" label="analogs &amp; derivatives"/> 
      <node id="Y03.030" label="antagonists &amp; inhibitors"/> 
      <node id="Y03.040" label="chemical synthesis"/> 
      <node id="Y03.010" label="agonists"/> 
     </isComposedBy> 
    </node> 
    <node id="Y07" label="pharmacology"> 
     <isComposedBy> 
      <node id="Y07.010" label="administration &amp; dosage"/> 
      <node id="Y07.020" label="adverse effects"> 
       <isComposedBy> 
        <node id="Y07.020.010" label="poisoning"/> 
        <node id="Y07.020.020" label="toxicity"/> 
       </isComposedBy> 
      </node> 
      <node id="Y07.030" label="agonists"/> 
      <node id="Y07.040" label="antagonists &amp; inhibitors"/> 
      <node id="Y07.050" label="contraindications"/> 
      <node id="Y07.070" label="pharmacokinetics"/> 
     </isComposedBy> 
    </node> 
    </isComposedBy> 
</node> 

我现在的问题是,在我的输入示例中,一些术语如agonistsantagonists &amp; inhibitors有多个TreeNumber。在这种情况下,我提到的术语出现在pharmacologychemistry树中。以下是我的输出xml,其中术语agonistsantagonists &amp; inhibitors仅出现在chemistry部分中。我想根据他们的TreeNumber出现他们。我从这篇文章的基础上根据我的XSLT:https://stackoverflow.com/a/31373764/1919069了解如何基于其TreeNumber创建层次结构。

<node id="MeSH" label="NIH MeSH Qualifiers"> 
    <isComposedBy> 
    <node id="Y03" label="chemistry"> 
     <isComposedBy> 
      <node id="Y03.010" label="agonists"/> 
      <node id="Y03.020" label="analogs &amp; derivatives"/> 
      <node id="Y03.030" label="antagonists &amp; inhibitors"/> 
      <node id="Y03.040" label="chemical synthesis"/> 
     </isComposedBy> 
    </node> 
    <node id="Y07" label="pharmacology"> 
     <isComposedBy> 
      <node id="Y07.070" label="pharmacokinetics"/> 
      <node id="Y07.050" label="contraindications"/> 
      <node id="Y07.010" label="administration &amp; dosage"/> 
      <node id="Y07.020" label="adverse effects"> 
       <isComposedBy> 
        <node id="Y07.020.010" label="poisoning"/> 
        <node id="Y07.020.020" label="toxicity"/> 
       </isComposedBy> 
      </node> 
     </isComposedBy> 
    </node> 
    </isComposedBy> 
</node> 

回答

2

这是一个有点尴尬的XSLT 1.0,其中一个节点的关键不能包含多个(尽管它可以包含几个节点)做的。不过,这是不是太难解决的限制:

XSLT 1.0

<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:key name="child" match="TreeNumber" use="substring(., 1, string-length() - 4)" /> 

<xsl:template match="QualifierRecordSet"> 
    <node id="MeSH" label="NIH MeSH Qualifiers"> 
     <isComposedBy> 
      <xsl:apply-templates select="QualifierRecord[not(contains(TreeNumber, '.'))]"/> 
     </isComposedBy> 
    </node> 
</xsl:template> 

<xsl:template match="QualifierRecord"> 
    <node id="{TreeNumber}" label="{String}"> 
     <xsl:variable name="children" select="key('child', TreeNumber)" /> 
     <xsl:if test="$children"> 
      <isComposedBy> 
       <xsl:apply-templates select="$children"/> 
      </isComposedBy> 
     </xsl:if> 
    </node> 
</xsl:template> 

<xsl:template match="TreeNumber"> 
    <node id="{.}" label="{../String}"> 
     <xsl:variable name="children" select="key('child', .)" /> 
     <xsl:if test="$children"> 
      <isComposedBy> 
       <xsl:apply-templates select="$children"/> 
      </isComposedBy> 
     </xsl:if> 
    </node> 
</xsl:template> 

</xsl:stylesheet>