【问题标题】:Transform XML elements into Attributes将 XML 元素转换为属性
【发布时间】:2017-06-17 18:04:54
【问题描述】:

我必须将一个 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>

【问题讨论】:

  • 这是基本的 XSLT,没有什么“有趣”的地方。学习使用xsl:attribute 指令,或者——甚至更好地——了解属性值模板

标签: xml xslt xml-attribute


【解决方案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]"/>

这部分将由该模板处理,不输出任何内容。具有这种模式的模板将比简单的&lt;xsl:template match="PART"&gt; 模板具有更高的优先级,但我建议为两者都添加一个priority 属性以明确。

对于第二种情况,您还可以使用PART[Code!=2] 轻松地反转逻辑。显然,根据您的具体需求推断。

【讨论】:

  • 太棒了!事实上,非常精确和优雅的解决方案。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-30
  • 2010-10-13
  • 1970-01-01
  • 2018-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多