简体   繁体   English

如何使用XSLT转换XML?

[英]How to transform XML using XSLT?

I've got a XML with this structure: 我有一个具有以下结构的XML:

<entities>
    <entity>
        <field>13</field>
    </entity>
    <entity>
        <field>1</field>
    </entity>
    <entity>
        <field>5</field>
    </entity>
</entities>

and I need to transform it to that structure using XSLT: 我需要使用XSLT将其转换为该结构:

<entities>
    <entity field="13"/>
    <entity field="1"/>
    <entity field="5"/>
</entities>

That's my XSLT for now: 现在是我的XSLT:

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

    <xsl:template match="field/text()">
        <xsl:value-of select="concat('&quot;', ., '&quot;')"/>
    </xsl:template>

I'm stuck with transforming <field> into entity's attribute. 我一直坚持将<field>转换为实体的属性。 How to do that? 怎么做?

I would match at the entity level rather than the field level and do something like this: 我将在实体级别而不是字段级别进行匹配,并执行以下操作:

<xsl:template match="entity">
 <entity>
  <xsl:attribute name="field"><xsl:value-of select="field/text()" /></xsl:attribute>
 </entity>
</xsl:template>

Edit: The above assumes a generic matching template as well, like in the original question. 编辑:上面也假设一个通用的匹配模板,就像在原始问题中一样。 For clarity, here is the full XSL file I tested against the sample input. 为了清楚起见,这是我针对示例输入测试的完整XSL文件。 As noted in the comments, you may want to match only against entity nodes in the entities node, although for the simple sample provided, it doesn't matter. 如注释中所述,您可能只想与实体节点中的实体节点进行匹配,尽管对于提供的简单示例而言,这并不重要。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="entity">
        <entity>
        <xsl:attribute name="field"><xsl:value-of select="field/text()" /></xsl:attribute>
        </entity>
    </xsl:template>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

This produces the output (tested in Eclipse on Mac): 产生输出(在Mac上的Eclipse中测试):

<?xml version="1.0" encoding="UTF-8"?>
<entities>
    <entity field="13"/>
    <entity field="1"/>
    <entity field="5"/>
</entities>

Try this: 尝试这个:

<xsl:for-each select="entities/entity">
    <xsl:element name="entity">
        <xsl:attribute name="field">
            <xsl:value-of select="field"/>
        </xsl:attribute>
    </xsl:element>
</xsl:for-each>

This code will go through all the entity elements and create an element with the field attribute for each one 此代码将遍历所有entity元素,并为每个元素创建一个具有field属性的元素

Somewhat verbose version: Both these might also target the specific internal entity not just "field" but I left it generic since that is all we see in the sample. 有点冗长的版本:这两个对象也都可能针对特定的内部实体而不仅仅是“字段”,但我将其保留为通用名称,因为这是我们在样本中看到的全部内容。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

  <xsl:template match="entities">
     <entities>
        <xsl:apply-templates/>
     </entities>
  </xsl:template>

  <xsl:template match="entity">
    <entity>
      <xsl:for-each select="*">
        <xsl:attribute name="{name()}">
          <xsl:value-of select="text()"/>
        </xsl:attribute>
      </xsl:for-each>
    </entity>
  </xsl:template>
</xsl:stylesheet>

Output 输出量

<entities xmlns="http://www.w3.org/1999/xhtml">
    <entity field="13"></entity>
    <entity field="1"></entity>
    <entity field="5"></entity>
</entities>

Slightly different version with "transform" 版本与“转换”略有不同

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="entities">
    <entities> 
        <xsl:apply-templates/>
    </entities>
  </xsl:template>

  <xsl:template match="entity">
    <entity>
      <xsl:for-each select="*">
        <xsl:attribute name="{name()}">
          <xsl:value-of select="text()"/>
        </xsl:attribute>
      </xsl:for-each>
    </entity>
  </xsl:template>
</xsl:transform>

Target JUST the field inner elements: 目标只是字段内部元素:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="entities">
    <entities> 
        <xsl:apply-templates/>
    </entities>
  </xsl:template>

  <xsl:template match="entity">
    <entity>
      <xsl:for-each select="field">
        <xsl:attribute name="{name()}">
          <xsl:value-of select="text()"/>
        </xsl:attribute>
      </xsl:for-each>
    </entity>
  </xsl:template>
</xsl:transform>

Example to do copy and just target the field, no closing tag on entity, also omits the xml declaration. 复制并仅定位字段的示例,实体上没有结束标记,并且省略了xml声明。

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="entities">
     <xsl:copy> 
        <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="entity">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

   <xsl:template match="field">
        <xsl:attribute name="{name()}">
          <xsl:value-of select="text()"/>
        </xsl:attribute>
    </xsl:template>
</xsl:transform>

Output: 输出:

<entities>
   <entity field="13"/>
   <entity field="1"/>
   <entity field="5"/>
</entities>

More Compact version of last one: 最后一个的更紧凑版本:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="entities|entity">
     <xsl:copy> 
        <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="field">
        <xsl:attribute name="{name()}">
          <xsl:value-of select="text()"/>
        </xsl:attribute>
    </xsl:template>
</xsl:transform>

Note This is different from the prior answer, it is more generic, just making ANY nested <field></field> into an attribute on its parent node. 注意这与先前的答案不同,它更通用,只是将ANY嵌套的<field></field>放入其父节点的属性中。 This cares nothing about the entities or entity elements specifically and more closely matches your question xsl. 这与entitiesentity元素无关,并且与您的问题xsl更紧密匹配。

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="@*|node()[not(self::field)]">
     <xsl:copy> 
        <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="field">
        <xsl:attribute name="{name()}">
          <xsl:value-of select="text()"/>
        </xsl:attribute>
    </xsl:template>
</xsl:transform>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM