【问题标题】:Converting XML elements to XML attributes using XSLT使用 XSLT 将 XML 元素转换为 XML 属性
【发布时间】:2010-10-13 21:56:44
【问题描述】:

我们有一个当前系统可以输出以下格式的 XML 文件:

<INVENTORY>
   <ITEM>
      <SERIALNUMBER>something</SERIALNUMBER>
      <LOCATION>something</LOCATION>
      <BARCODE>something</BARCODE>
   </ITEM>
</INVENTORY>

我需要使用这些数据加载到标准的 .NET 2.0 网格中。但是网格需要 XML 格式如下:

<INVENTORY>
   <ITEM serialNumber="something" location="something" barcode="something">
   </ITEM>
</INVENTORY>

即item的子节点需要转化为item节点的属性。

有人知道如何使用 XSLT 做到这一点吗?

【问题讨论】:

  • 请阅读标记文档,您需要 4 个空格或一个制表符,以便 SO 识别代码。
  • 你接受的答案不会产生你想要的结果!!!一个属性名称必须是“serialNumber”,接受的解决方案产生“serialnumber”。下次不要误导那些花时间提供帮助的人。

标签: xml xslt


【解决方案1】:

应该这样做:

  <xsl:for-each select="//ITEM">
    <xsl:element name="ITEM">
      <xsl:attribute name="serialNumber">
        <xsl:value-of select="SERIALNUMBER"/>
      </xsl:attribute>
      <xsl:attribute name="location">
        <xsl:value-of select="LOCATION"/>
      </xsl:attribute>
      <xsl:attribute name="barcode">
        <xsl:value-of select="BARCODE"/>
      </xsl:attribute>
    </xsl:element>
  </xsl:for-each>

或者使用大卫的快捷方式:

<xsl:for-each select="//ITEM">
  <ITEM serialNumber="{SERIALNUMBER}" location="{LOCATION}" barcode="{BARCODE}"/>
</xsl:for-each>

【讨论】:

    【解决方案2】:

    如果您的来源如下所示:

    <row><a>1</a><b>2</b></row>
    

    你希望它看起来像这样:

    <row a="1" b="2" />
    

    那么这个 XSLT 应该可以工作了:

    <xsl:template match="row">
        <row a="{a}" b="{b}" />
    </xsl:template>
    

    【讨论】:

      【解决方案3】:

      这两个模板应该可以做到:-

      <xsl:template match="ITEM">
         <ITEM serialNumber="{SERIALNUMBER}" location="{LOCATION}" barcode="{BARCODE}" />
      </xsl:template>
      
      <xsl:template match="INVENTORY">
         <INVENTORY>
            <xsl:apply-templates />
         </INVENTORY>
      </xsl:template>
      

      【讨论】:

        【解决方案4】:

        这应该可行:

        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
          <xsl:template match="INVENTORY">
            <INVENTORY>
              <xsl:apply-templates/>
            </INVENTORY>
          </xsl:template>
        
          <xsl:template match="ITEM">
            <ITEM>
              <xsl:for-each select="*">
                <xsl:attribute name="{name()}">
                  <xsl:value-of select="text()"/>
                </xsl:attribute>
        
              </xsl:for-each>
            </ITEM>
          </xsl:template>
        </xsl:stylesheet>
        

        【讨论】:

          【解决方案5】:

          这可能是最简单的解决方案,它将ITEM 的任何子元素转换为其属性,并按原样复制其他所有内容,同时将元素名称转换为任何所需的属性名称:

          <xsl:stylesheet version="1.0" 
           xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
           <xsl:output omit-xml-declaration="yes" indent="yes"/>
          <!--                                              --> 
            <xsl:strip-space elements="*"/>
          
            <xsl:variable name="vrtfNameMapping">
              <item name="SERIALNUMBER" newName="serialNumber"/>
              <item name="LOCATION" newName="location"/>
              <item name="BARCODE" newName="barcode"/>
            </xsl:variable>
           <!--                                              --> 
            <xsl:variable name="vNameMapping" select=
            "document('')/*/xsl:variable[@name='vrtfNameMapping']"/>
          <!--                                              --> 
          
            <xsl:template match="node()|@*">
              <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
              </xsl:copy>
            </xsl:template>
          <!--                                              --> 
            <xsl:template match="ITEM/*">
              <xsl:attribute name=
               "{$vNameMapping/*[@name=name(current())]/@newName}">
                <xsl:value-of select="."/>
              </xsl:attribute>
            </xsl:template>
          </xsl:stylesheet>
          

          当上述转换应用于提供的 XML 文档时

          <INVENTORY>
              <ITEM>
                  <SERIALNUMBER>something</SERIALNUMBER>
                  <LOCATION>something</LOCATION>
                  <BARCODE>something</BARCODE>
              </ITEM>
          </INVENTORY>
          

          产生想要的结果

          <INVENTORY>
             <ITEM serialNumber="something" location="something" barcode="something"/>
          </INVENTORY>
          

          请注意以下几点:

          1. identity rule的使用

          2. &lt;xsl:strip-space elements="*"/&gt;的使用

          3. 变量vrtfNameMapping的使用没有任何xxx:node-set()扩展函数。

          4. 事实上,我们处理名称和 newName 之间的任何映射,而不仅仅是简单的小写。

          【讨论】:

          • 看起来这种转换不起作用。它没有产生任何结果。就是这样:
          • @Mark,这意味着您要么有一个有问题的 XSLT 处理器,要么没有准确地复制和粘贴 XML 文档和转换。我刚刚重新执行了转换——使用多个 XSLT 处理器产生了相同的结果
          猜你喜欢
          • 2018-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-06-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多