Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 选择唯一属性组_Xml_Xslt - Fatal编程技术网

Xml 选择唯一属性组

Xml 选择唯一属性组,xml,xslt,Xml,Xslt,我的xslt背景很差,需要转换如下所示的XML: <row attribute1="1" attribute2="something" attribute3="somevalue"> <row attribute1="1" attribute2="something" attribute3="somevalue"> <row attribute1="2" attribute2="anotherthing" attribute3="somevalue"> &l

我的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 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)或行元素的所有属性


提前感谢。

您可以轻松地转换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>

巴辛加


您可以轻松地转换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>

巴辛加


如果您想进一步了解XSLT的复杂性,您可能有兴趣了解一种称为XSLT的技术,它可以用来解决您的问题。要获得不同的行,可以通过attribute1对它们进行有效分组,然后为每个组选择组中的第一个元素。(或丢弃不是第一个的元素)。在XSLT1.0中,Muenchian分组是实现这一点的最有效方法

在本例中,首先定义一个键来指示您的组,在本例中,该组是按属性1分组的元素

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

然后,如果您想选择不同的元素,您可以为其给定的属性1选择键中首先出现的元素

<xsl:key name="row" match="row" use="@attribute1" />
<xsl:apply-templates select="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])]" />  


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

如果您想进一步了解XSLT的复杂性,您可能有兴趣了解一种称为XSLT的技术,它可以用来解决您的问题。要获得不同的行,可以通过attribute1对它们进行有效分组,然后为每个组选择组中的第一个元素。(或丢弃不是第一个的元素)。在XSLT1.0中,Muenchian分组是实现这一点的最有效方法

在本例中,首先定义一个键来指示您的组,在本例中,该组是按属性1分组的元素

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

然后,如果您想选择不同的元素,您可以为其给定的属性1选择键中首先出现的元素

<xsl:key name="row" match="row" use="@attribute1" />
<xsl:apply-templates select="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])]" />  


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

非常感谢,它成功了。如果我想通过多个属性进行过滤,我应该将它们添加到“前面的兄弟姐妹”表达式中?对。如果您想按不同的attribute1和attribute3对进行筛选,那么应该是行[前面的兄弟姐妹::行/\@attribute1=\@attribute1和前面的兄弟姐妹::行/\@attribute3=\@attribute3](忽略反斜杠…因此抱怨我试图通知太多用户)是否有可能更改和标记文本?我会试着回答,但如果我误解了你,你必须开始一个新的问题。。。你只需要在“表”上匹配;不使用xsl:copy,只输出“Table”元素。。。非常感谢,它成功了。如果我想通过多个属性进行过滤,我应该将它们添加到“前面的兄弟姐妹”表达式中?对。如果您想按不同的attribute1和attribute3对进行筛选,那么应该是行[前面的同级::行/\@attribute1=\@attribute1和前面的同级::行/\@attribute3=\@attribute3](忽略反斜杠…所以