4

我有以下 XML:-

<inventory>
  <item>
    <name_element>
      <!--some structure-->
    </name_element>
    <some_element1>val1</some_element1>
    <some_element2>val2</some_element2>
    <!-- some more elements -->
  </item>
  <!-- lots of items -->
</inventory>

现在我想将其转换为:-

<inventory>
  <item some_element1="val1" some_element2="val2" ... >
    <name_element>
      <!-- as it is -->
    </name_element>
</inventory>

基本上我对 some_elements 的名称/类型一无所知,任何项目都可以有任意数量的这些元素。我确实知道它们都是简单的类型并且可以转换为属性。

我已经阅读了使用 XSLT 将 XML 元素转换为 XML 属性,它告诉我如何将所有子元素转换为属性,但不清楚如何排除特定的“name_element”被转换为属性。

4

3 回答 3

7
<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">
    <xsl:output indent="yes" method="xml"/>

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

    <xsl:template match="item">
        <xsl:copy>
            <!--apply templates for any attributes and convert 
                elements(except for name_element) in order to create all 
                attributes before creating child nodes for item element -->
            <xsl:apply-templates select="@* 
                                         | *[not(self::name_element)]"/>
            <!--apply templates to name_element and any comments or processing instructions -->
            <xsl:apply-templates select="name_element 
                                         | comment() 
                                         | processing-instruction()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="item/*[not(self::name_element)]">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>

</xsl:stylesheet>
于 2012-07-05T15:57:46.367 回答
3

首先,使用身份模板按原样复制所有内容:

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

然后,为项目定义一个模板。您可以迭代孩子,并排除您不希望转换为属性的内容。这是一个示例模板:

<xsl:template match="item">
 <xsl:copy>
   <!-- this will set children as attributes, but name_element -->
   <xsl:for-each select="*[not(local-name()='name_element')]">
        <xsl:attribute name="{local-name()}">
          <xsl:value-of select="text()"/>
        </xsl:attribute>
   </xsl:for-each>

   <!-- this preserves name_element as it is -->
   <xsl:apply-templates select="name_element"/>
 </xsl:copy>
</xsl:template>
于 2012-07-05T15:57:37.673 回答
1

尝试

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="item">
        <xsl:copy>
            <xsl:apply-templates select="*[not(self::name_element)]"/>
            <xsl:apply-templates select="name_element"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="item/*[not(self::name_element)]">
        <xsl:attribute name="{name()}">
            <xsl:value-of select="."/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>
于 2012-07-05T15:57:54.023 回答