通过xslt组合xml节点

时间:2015-06-30 09:20:35

标签: xml xslt

我有以下xml代码(简化后,假名始终存在,但患者也可能是另一个内容不同的标签):

    <Record>
    <Pseudonyms>
        <Pseudonym type="B">e113</Pseudonym>
        <Pseudonym type="M">lss9</Pseudonym>
        <Pseudonym type="S">f6rr</Pseudonym>
    </Pseudonyms>
    <Data>
        <patient>
            <Sexe>V</Sexe>
            <yob>1984</yob>
            <status>2</status>
        </patient>
    </Data>
    </Record>

我正在寻找xslt解决方案,结果如下:

    <Record>
        <patient>
            <B>e113</B>
            <M>lss9</M>
            <S>f6rr</S>
            <Sexe>V</Sexe>
            <yob>1984</yob>
            <status>2</status>
        </patient>  
       </Record>

问题是我如何将假名标签和(在这种情况下,患者标签)组合成一条记录。如上所述,这是一个简化的例子。 Patient-tag也可以是同一文档中的其他标签。所以我需要一个通用的解决方案,它将Pseudonyms-tag之后的所有标签与之后的标签前缀(在本例中为Patient)结合起来。

我知道如何将<Pseudonym type="B">e113</Pseudonym>转换为<B>e113</B>,但我不知道如何以正确的方式组合标记以获得示例中的结果。

我希望我能够很好地解释我试图帮助的事情。蒂亚。

编辑:

我没有提到的是,患者只是众多不同标签中的一种。所以简短的版本是:

XML

    <?xml version="1.0" encoding="UTF-8"?>
    <Bestand>
    <Record>
    <Pseudonyms>
        <Pseudonym type="B">e113</Pseudonym>
        <Pseudonym type="M">lss9</Pseudonym>
        <Pseudonym type="S">f6rr</Pseudonym>
    </Pseudonyms>
    <Data>
        <Patient>
            <Sexe>V</Sexe>
            <yob>1984</yob>
            <status>2</status>
        </Patient>
    </Data>
    </Record>

    <Record>
    <Pseudonyms>
        <Pseudonym type="B">e113</Pseudonym>
        <Pseudonym type="M">lss9</Pseudonym>
        <Pseudonym type="S">f6rr</Pseudonym>
    </Pseudonyms>
    <Data>
        <SurveyA>
            <Item01>1</Item01>
            <Item02>4</Item02>
            <Item03>8</Item03>
        </SurveyA>
    </Data>
    </Record>
    <Record>
    <Pseudonyms>
        <Pseudonym type="B">e113</Pseudonym>
        <Pseudonym type="M">lss9</Pseudonym>
        <Pseudonym type="S">f6rr</Pseudonym>
    </Pseudonyms>
    <Data>
        <SurveyB>
            <Item01>1</Item01>
            <Item02>3</Item02>
            <Item03>2</Item03>
        </SurveyB>
    </Data>
    </Record>

   </Bestand>

我的xsl看起来像:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="/">
    <xsl:element name="message">            
         <xsl:apply-templates select="//Data"/>                  
    </xsl:element>
    </xsl:template>

    <xsl:template match="Patient|SurveyA|SurveyB">          
        <xsl:element name="{name()}">           
            <xsl:element name="B"><xsl:value-of select="//Pseudonyms/Pseudonym[@type='B']" /></xsl:element>
            <xsl:element name="M"><xsl:value-of select="//Pseudonyms/Pseudonym[@type='M']" /></xsl:element>
            <xsl:element name="S"><xsl:value-of select="//Pseudonyms/Pseudonym[@type='S']" /></xsl:element>
            <xsl:copy-of select="node()"/>
        </xsl:element>      
    </xsl:template>     
</xsl:stylesheet>

这导致下一个输出是我想要的,但我也想知道会有更好,更清洁的方式。

![Output][1]
[1]: http://i.stack.imgur.com/1Lcea.png

如上所述,这有效,我只剩下一个问题,可能有多个Patient,SurveyA和SurveyB记录。当我应用我的样式表时,整个事情没有排序。因此,可以存在患者记录,然后是SurveyA记录。此SurveyA记录可以依次显示患者记录。如果我可以对特定项目进行分组,那就太好了。这个我还没有能够帮凶。

2 个答案:

答案 0 :(得分:1)

这是实现目标的一种方式:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/Record">
    <Record>
        <patient>
            <xsl:apply-templates select="Pseudonyms/Pseudonym" />
            <xsl:apply-templates select="Data/patient/*" />
        </patient>
    </Record>
</xsl:template>

<xsl:template match="Pseudonym">
    <xsl:element name="{@type}">
        <xsl:value-of select="." />
    </xsl:element>
</xsl:template>

<xsl:template match="*">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

这是一个类似于四十二个答案的选项,但考虑到了您的更新问题。

注意:

  • 我还要按Pseudonym@type进行排序。如果这不是必要的,只需删除xsl:sort
  • 我使用单独的模板来处理Pseudonym元素的转换。如果它们与问题中显示的一样静态,您可以返回使用xsl:value-of对元素进行硬编码。 (但您不需要使用xsl:element

XML输入(略微修改以显示排序)

<Bestand>
    <Record>
        <Pseudonyms>
            <Pseudonym type="B">e113a</Pseudonym>
            <Pseudonym type="M">lss9a</Pseudonym>
            <Pseudonym type="S">f6rra</Pseudonym>
        </Pseudonyms>
        <Data>
            <Patient>
                <Sexe>V</Sexe>
                <yob>1984</yob>
                <status>2</status>
            </Patient>
        </Data>
    </Record>

    <Record>
        <Pseudonyms>
            <Pseudonym type="B">e113</Pseudonym>
            <Pseudonym type="M">lss9</Pseudonym>
            <Pseudonym type="S">f6rr</Pseudonym>
        </Pseudonyms>
        <Data>
            <SurveyA>
                <Item01>1</Item01>
                <Item02>4</Item02>
                <Item03>8</Item03>
            </SurveyA>
        </Data>
    </Record>

    <Record>
        <Pseudonyms>
            <Pseudonym type="M">lss9</Pseudonym>
            <Pseudonym type="B">e113</Pseudonym>
            <Pseudonym type="S">f6rr</Pseudonym>
        </Pseudonyms>
        <Data>
            <Patient>
                <Sexe>W</Sexe>
                <yob>1985</yob>
                <status>3</status>
            </Patient>
        </Data>
    </Record>


    <Record>
        <Pseudonyms>
            <Pseudonym type="B">e113</Pseudonym>
            <Pseudonym type="M">lss9</Pseudonym>
            <Pseudonym type="S">f6rr</Pseudonym>
        </Pseudonyms>
        <Data>
            <SurveyB>
                <Item01>1</Item01>
                <Item02>3</Item02>
                <Item03>2</Item03>
            </SurveyB>
        </Data>
    </Record>

</Bestand>

XSLT 1.0

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

    <xsl:template match="/*">
        <message>
            <xsl:apply-templates select="Record/Data/*">
                <xsl:sort select="local-name()"/>
            </xsl:apply-templates>
        </message>          
    </xsl:template>

    <xsl:template match="Data/*">          
        <xsl:copy>
            <xsl:apply-templates select="../../Pseudonyms/Pseudonym">
                <xsl:sort select="@type"/>
            </xsl:apply-templates>
            <xsl:copy-of select="node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="Pseudonym">
        <xsl:element name="{@type}">
            <xsl:value-of select="."/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

XML输出

<message>
   <Patient>
      <B>e113a</B>
      <M>lss9a</M>
      <S>f6rra</S>
      <Sexe>V</Sexe>
      <yob>1984</yob>
      <status>2</status>
   </Patient>
   <Patient>
      <B>e113</B>
      <M>lss9</M>
      <S>f6rr</S>
      <Sexe>W</Sexe>
      <yob>1985</yob>
      <status>3</status>
   </Patient>
   <SurveyA>
      <B>e113</B>
      <M>lss9</M>
      <S>f6rr</S>
      <Item01>1</Item01>
      <Item02>4</Item02>
      <Item03>8</Item03>
   </SurveyA>
   <SurveyB>
      <B>e113</B>
      <M>lss9</M>
      <S>f6rr</S>
      <Item01>1</Item01>
      <Item02>3</Item02>
      <Item03>2</Item03>
   </SurveyB>
</message>