将XML元素转换为属性

时间:2017-02-01 05:00:22

标签: xml xslt xml-attribute

我必须将一个XML文件转换为适合特定需求的另一个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 个答案:

答案 0 :(得分:1)

这里有很多选择。蛮力方法只是使用属性值模板(将属性值作为{..}中的表达式)来执行

<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]轻松地反转逻辑。显然,根据您的具体需求推断它。