0

我的 xslt 背景很差,我需要转换如下所示的 XML:

<row attribute1="1" attribute2="something" attribute3="somevalue">
<row attribute1="1" attribute2="something" attribute3="somevalue">
<row attribute1="2" attribute2="anotherthing" attribute3="somevalue">

在看起来像这样的东西中:

<row attribute1="1">
<row attribute1="2">

转换任务还有两个要求。我想得到与上面相同的结果,但我想更改属性名称,例如:

<row new_name_for_attribute1="1">
<row new_name_for_attribute1="2">

最后一个要求是该方法可以应用于单个属性(如前面的示例)、它们的子集(attribute1 和 attribute3)或行元素的所有属性

提前致谢。

4

2 回答 2

2

如果您想进一步了解 XSLT 的复杂性,您可能有兴趣了解一种称为Muenchian Grouping的技术,该技术可用于解决您的问题。要获得不同的行,您可以按attribute1有效地将它们分组,然后为每个组选择组中的第一个元素。(或者丢弃不是第一个的元素)。Muenchian Grouping 是在 XSLT 1.0 中实现这一目标的最有效方式。

在这种情况下,您首先定义一个键来指示您的组,在您的情况下是元素,按attribute1分组

<xsl:key name="row" match="row" use="@attribute1" />

如果您想选择不同的元素,您将选择在给定属性的键中首先出现的行元素1

<xsl:apply-templates select="row[generate-id() = generate-id(key('row', @attribute1)[1])]" />

或者,您可以有一个模板来忽略重复的元素(即不是组中的第一个)

<xsl:template match="row[generate-id() != generate-id(key('row', @attribute1)[1])]" />

试试这个 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>
   <xsl:key name="row" match="row" use="@attribute1" />

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

   <xsl:template match="row[generate-id() != generate-id(key('row', @attribute1)[1])]" />   
</xsl:stylesheet>

应用于以下 XML 时

<rows>
   <row attribute1="1" attribute2="something" attribute3="somevalue" />
   <row attribute1="1" attribute2="something" attribute3="somevalue" />
   <row attribute1="2" attribute2="anotherthing" attribute3="somevalue" />
</rows>

以下是输出

<rows>
   <row attribute1="1" attribute2="something" attribute3="somevalue"></row>
   <row attribute1="2" attribute2="anotherthing" attribute3="somevalue"></row>
</rows>

XSLT 可以很容易地扩展为重命名属性,或者排除它们,如 ljdelight 的回答中所述。此外,如果您想在测试中包含第二个属性,您可以像这样扩展您的密钥:

<xsl:key name="row" match="row" use="concat(@attribute1, '|', @attribute3)" />

并且忽略重复项,模板看起来像这样

<xsl:template match="row
     [generate-id() != generate-id(key('row', concat(@attribute1, '|', @attribute3))[1])]" />  

这里唯一需要注意的是管道字符 | 的使用。作为分隔符。如果需要,这可以是任何其他字符,只要它不出现在属性值中即可。

于 2013-03-05T20:58:36.210 回答
1

您可以轻松地转换 XML。这里有一个小代码,你可以学习一些xsl。

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes" />
   <xsl:template match="@*|node()">
       <xsl:copy>
           <xsl:apply-templates select="@*|node()"/>
       </xsl:copy>
   </xsl:template>

   <!-- drop a row that matches a previous row of the same id -->
   <xsl:template match="row[ preceding-sibling::row/@attribute1 = @attribute1 ]" />

   <!-- do stuff with the row. this template is equivalent to the default template copy. -->
   <xsl:template match="row">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()" />
      </xsl:copy>
   </xsl:template>

   <!-- drop attribute2 attributes -->
   <xsl:template match="@attribute2" />

   <!-- rename attribute1 -->
   <xsl:template match="@attribute1">
      <xsl:attribute name="new_name_for_attribute1">
         <xsl:value-of select="."/>
      </xsl:attribute>
   </xsl:template>
</xsl:stylesheet>

使用此输入:

<table>
   <row attribute1="1" attribute2="something" attribute3="somevalue">
      <p>foo</p>
   </row>
   <row attribute1="1" attribute2="something" attribute3="somevalue">
      <p>bar</p>
   </row>
   <row attribute1="2" attribute2="anotherthing" attribute3="somevalue">
      <p>bazinga</p>
   </row>
</table>

为您提供以下输出:

<table>
   <row new_name_for_attribute1="1" attribute3="somevalue">
      <p>foo</p>
   </row>
   <row new_name_for_attribute1="2" attribute3="somevalue">
      <p>bazinga</p>
   </row>
</table>
于 2013-03-05T10:24:06.843 回答