代码之家  ›  专栏  ›  技术社区  ›  Srikrishna Pothukuchi

将XML元素转换为属性

  •  0
  • Srikrishna Pothukuchi  · 技术社区  · 8 年前

    我必须将一个XML文件转换为另一组适合特定需求的文件。转换XML并不新鲜,但将其从元素动态转换为属性有点有趣。

    此外,还需要使用子元素的文本值查询父元素。

    这就是我想要实现的(数据是匿名的):

    源文件

    <PARTS>
        <PART>
            <Name>Valve</Name>
            <Code>1</Code>
            <Color>Brown</Color>
        </PART>
        <PART>
            <Name>Filter</Name>
            <Code>2</Code>
            <Color>Green</Color>
        </PART>
        <PART>
            <Name>Plug</Name>
            <Code>3</Code>
            <Color>Brown</Color>
        </PART>
    </PARTS>
    

    转换到目标XML文件1,对颜色子元素进行过滤:

    <PARTS>
        <PART Name="Valve" Code=1 Color="Brown" />
        <PART Name="Plug" Code=3 Color="Brown" />
    </PARTS>
    

    转换到目标XML文件2,对颜色子元素进行过滤:

    <PARTS>
        <PART Name="Filter" Code=2 Color="Green" />
    </PARTS>
    
    1 回复  |  直到 8 年前
        1
  •  1
  •   Flynn1179    8 年前

    这里有许多选项。暴力方法只是使用属性值模板(将属性值作为表达式放入 {..} )做

    <xsl:template match="PART">
      <PART Name="{Name}" Code="{Code}" Color="{Color}"/>
    </xsl:template>
    

    或者更广义的

    <xsl:template match="PART">
      <xsl:for-each select="*">
        <xsl:attribute name="local-name()">
          <xsl:value-of select="."/>
        </xsl:attribute>
      </xsl:for-each>
    </xsl:template>
    

    或者,您可以在的子节点上使用泛化模板泛化处理子元素 PART :

    <xsl:template match="PART/*">
      <xsl:attribute name="local-name()">
        <xsl:value-of select="."/>
      </xsl:attribute>
    </xsl:template>
    

    你也可以匹配 "Name | Color | Code" "*[parent::PART]" ,但后者的性能较差。

    至于过滤掉不需要的节点,这是一个单独的过程。如果您定义了一个没有内容的适当匹配模板,它将不会在输出中产生任何内容。所以在第一种情况下,你可以

    <xsl:template match="PART[Code=2]"/>
    

    该部分将由该模板处理,不输出任何内容。具有此模式的模板将具有比简单模板更高的优先级 <xsl:template match="PART"> 模板,但我建议添加 priority 属性都要清除。

    您还可以使用以下命令轻松地反转逻辑: PART[Code!=2] 对于你的第二个案例。显然,根据您的具体需求进行推断。