将 XML 个元素转换为属性
Transform XML elements into Attributes
我必须将一个 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>
这里有多种选择。暴力破解的方法就是使用属性值模板(将一个属性值作为表达式放在{..}
中)做
<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]
轻松地反转逻辑。显然,将其推断为您的特定需求。
我必须将一个 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>
这里有多种选择。暴力破解的方法就是使用属性值模板(将一个属性值作为表达式放在{..}
中)做
<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]
轻松地反转逻辑。显然,将其推断为您的特定需求。