在XSLT中删除基于属性值的重复值,而不对硬件编码属性名称

时间:2016-12-09 09:45:23

标签: xslt xslt-1.0 xslt-2.0 xslt-grouping

下面我有一段xml元素,它们是我的xml文档的一部分。 需要根据属性值和动态元素值过滤元素,这意味着不实际硬编码属性值(例如:@id或@name)。  你能帮忙!!!

示例输入:

<Products>
    <product id='1'>568</product>
    <product id='1'>598</product>
    <product name='8'>XYZ</product>
    <product name='8'>XYZ</product>
    <product category='9'>ABC</product>
</Products>

预期产出:

<Products>
    <product id='1'>568</product>
    <product id='1'>598</product>
    <product name='8'>XYZ</product>
    <product category='9'>ABC</product>
</Products>

2 个答案:

答案 0 :(得分:0)

从示例输入生成预期输出的最小示例样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:acf="http://www.acme-dummy/xslt/function"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="Class">
        <xsl:copy>
            <xsl:for-each-group select="student" group-by="acf:rolenoAndContent(.)">
                <xsl:copy-of select="."/>
            </xsl:for-each-group>
        </xsl:copy>
    </xsl:template>

    <xsl:function name="acf:rolenoAndContent" as="xs:string">
        <xsl:param name="prmStudent" as="element()"/>
        <xsl:sequence select="concat($prmStudent/@rollno,' ',$prmStudent)"/>
    </xsl:function>

</xsl:stylesheet>

如果要实现不对@rollno进行硬编码,只要您的输入为每个学生提供相同数量的属性,以下示例就会起作用:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:acf="http://www.acme-dummy/xslt/function"
    exclude-result-prefixes="xs"
    version="2.0">

   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="Class">
       <xsl:copy>
           <xsl:for-each-group select="student" group-by="acf:attsAndContent(.)">
               <xsl:copy-of select="."/>
           </xsl:for-each-group>
       </xsl:copy>
   </xsl:template>

   <xsl:function name="acf:attsAndContent" as="xs:string">
       <xsl:param name="prmStudent" as="element()"/>
       <xsl:variable name="attsAndValues" as="xs:string*">
           <xsl:for-each select="$prmStudent/@*">
                <xsl:sort select="name()"/>
                <xsl:sequence select="concat(name(),':',.)"/>
           </xsl:for-each>
       </xsl:variable>
       <xsl:sequence select="concat(string-join($attsAndValues,' '),' ',$prmStudent)"/>
   </xsl:function>

</xsl:stylesheet>

答案 1 :(得分:0)

假设你想要删除重复的兄弟姐妹,你可以使用deep-equal

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

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

    <xsl:template match="product[some $p in preceding-sibling::product satisfies deep-equal(., $p)]"/>

</xsl:stylesheet>