使用基于属性名称的XSLT过滤属性

时间:2012-01-02 09:19:01

标签: xslt attributes filter

很抱歉,如果之前已经讨论过,但是找不到适合我的问题的答案..... 我有这个xml:

<RootList>
<Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
<Extn ExtnAtt1="1">
<Child ChildAtt1="1" ChildAtt2="2"/>
</Extn>
</Root>
</RootList>

我想要的是如果除了存在的内容之外,如果在RootList \ Root \ Extn节点上有这个xml的任何额外属性,那么该属性将被删除。

所以如果输入如下:

<RootList>
<Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
<Extn ExtnAtt1="1" ExtnAtt2="2">
<Child ChildAtt1="1" ChildAtt2="2"/>
</Extn>
</Root>
</RootList>

然后输出将如下:

<RootList>
<Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
<Extn ExtnAtt1="1">
<Child ChildAtt1="1" ChildAtt2="2"/>
</Extn>
</Root>
</RootList>

为此我写了一个xsl:

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

<RootList>
<xsl:for-each select="/RootList">
<xsl:element name="Root">
<xsl:element name="Extn">
<xsl:attribute name="ExtnAtt1">
<xsl:value-of select="/RootList/Root/Extn/@ExtnAtt1"/>
</xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:for-each>
</RootList>
</xsl:template>
</xsl:stylesheet>

但是这给了我输出:

<?xml version="1.0" encoding="UTF-16"?>
<RootList>
<Root>
<Extn ExtnAtt1="1" />
</Root>
</RootList>

我想保留现有的xml,只想删除额外的属性。

任何人都可以帮助我。

先谢谢你们。

谢谢各位回复...你们摇滚...... 我想到了另一种方法......让我知道你对此有何看法......

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
   <xsl:output method="xml" indent="yes"/> 
<xsl:template match="/">
<xsl:apply-templates/>
<RootList>
<xsl:for-each select="/RootList">
<xsl:element name="Root">
<xsl:copy-of select="/RootList/Root/@RootAtt1"/>
<xsl:copy-of select="/RootList/Root/@RootAtt2"/>
<xsl:copy-of select="/RootList/Root/@RootAtt3"/>
<xsl:element name="Extn">
<xsl:copy-of select="/RootList/Root/Extn/@ExtnAtt1"/>
<xsl:element name="Child">
<xsl:copy-of select="/RootList/Root/Extn/Child/@ChildAtt1"/>
<xsl:copy-of select="/RootList/Root/Extn/Child/@ChildAtt2"/>
</xsl:element>
</xsl:element>
</xsl:element>
</xsl:for-each>
</RootList>
</xsl:template>
</xsl:stylesheet>

如果适用于:

<RootList>
<Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
<Extn ExtnAtt1="1" ExtnAtt2="2">
<Child ChildAtt1="1" ChildAtt2="2"/>
</Extn>
</Root>
</RootList>

它输出为:

<?xml version="1.0" encoding="UTF-16"?>
<RootList>
<Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
<Extn ExtnAtt1="1">
<Child ChildAtt1="1" ChildAtt2="2" />
</Extn>
</Root>
</RootList>

假设RootList \ Root \ Extn \ @ ExtnAtt2是不需要的属性。

由于 等待你的回复.... :)

干杯

3 个答案:

答案 0 :(得分:2)

执行此操作的一种方法是覆盖标识模板,并添加模板以匹配您要删除的属性,这将忽略它们。

<xsl:template match="Extn/@*[not(local-name() = 'ExtnAtt1')]" />

因此,给定以下XSLT:

<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>

   <xsl:template match="Extn/@*[not(local-name() = 'ExtnAtt1')]"/>
</xsl:stylesheet>

应用于以下XML

<RootList>   
  <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">   
    <Extn ExtnAtt1="1" ExtnAtt2="2">   
      <Child ChildAtt1="1" ChildAtt2="2"/>   
    </Extn>   
  </Root>   
</RootList> 

将输出以下内容:

<RootList>
  <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
    <Extn ExtnAtt1="1">
      <Child ChildAtt1="1" ChildAtt2="2"></Child>
    </Extn>
  </Root>
</RootList>

如果你需要在 Extn 元素上保留多个属性,另一种方法是使用这样的样式表,它明确地列出了要保留的属性:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="Extn">
      <xsl:copy>
         <xsl:apply-templates select="@ExtnAtt1|@ExtnAtt3|@ExtnAtt5|node()"/>
      </xsl:copy>
   </xsl:template>

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

应用于以下XML

<RootList>
  <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
    <Extn ExtnAtt1="1" ExtnAtt2="2" ExtnAtt3="3" ExtnAtt4="4" ExtnAtt5="5">
      <Child ChildAtt1="1" ChildAtt2="2"/>
    </Extn>
  </Root>
</RootList>

以下是输出

<RootList>
  <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
    <Extn ExtnAtt1="1" ExtnAtt3="3" ExtnAtt5="5">
      <Child ChildAtt1="1" ChildAtt2="2"></Child>
    </Extn>
   </Root>
</RootList>

请注意,除 Extn 元素外,所有其他元素不受影响。

答案 1 :(得分:0)

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
<xsl:output method="xml" indent="yes"/>

<xsl:template match="RootList">
<xsl:apply-templates select="Root"/>
</xsl:template>

<xsl:template match="Root | Extn | Child">
<xsl:copy>
<xsl:apply-templates select="@RootAtt1 | @RootAtt2 | @RootAtt3 | @ExtnAtt1 | @ChildAtt1 | @ChildAtt2" />
<xsl:apply-templates select="Root | Extn | Child"/>
</xsl:copy>
</xsl:template>


<xsl:template match="@RootAtt1 | @RootAtt2 | @RootAtt3 | @ExtnAtt1 | @ChildAtt1 | @ChildAtt2">
<xsl:copy-of select="."/>
</xsl:template>
</xsl:stylesheet>

答案 2 :(得分:0)

这是一个 true 解决方案,与当前接受的解决方案不同,它可以处理“严格”文档元素的任意数量的属性

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my" exclude-result-prefixes="my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <my:strict>
    <RootList>
        <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
            <Extn ExtnAtt1="1" ExtnAtt3="1">
                <Child ChildAtt1="1" ChildAtt2="2"/>
            </Extn>
        </Root>
    </RootList>
 </my:strict>

 <xsl:variable name="vStrict"
      select="document('')/*/my:strict"/>

 <xsl:template match="/">
  <xsl:apply-templates select="*">
      <xsl:with-param name="pstrictElement"
        select="$vStrict/*"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="*">
   <xsl:param name="pstrictElement"/>
     <xsl:copy>
       <xsl:apply-templates select="@*">
        <xsl:with-param name="pstrictElement"
             select="$pstrictElement"/>
       </xsl:apply-templates>

       <xsl:apply-templates select="*[1]">
        <xsl:with-param name="pstrictElement"
             select="$pstrictElement/*[1]"/>
       </xsl:apply-templates>

       <xsl:apply-templates select="following-sibling::*[1]">
        <xsl:with-param name="pstrictElement"
             select="$pstrictElement/following-sibling::*[1]"/>
       </xsl:apply-templates>
     </xsl:copy>
 </xsl:template>

 <xsl:template match="@*">
   <xsl:param name="pstrictElement"/>

    <xsl:copy-of select=
    "self::node()
       [$pstrictElement/@*[name() = name(current())]]"/>
 </xsl:template>
</xsl:stylesheet>

将此转换应用于以下XML文档

<RootList>
    <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
        <Extn ExtnAtt1="1" ExtnAtt2="1" ExtnAtt3="1" ExtnAtt4="1">
            <Child ChildAtt1="1" ChildAtt2="2"/>
        </Extn>
    </Root>
</RootList>

生成了想要的,正确的,清洁的结果

<RootList>
   <Root RootAtt1="1" RootAtt2="2" RootAtt3="3">
      <Extn ExtnAtt1="1" ExtnAtt3="1">
         <Child ChildAtt1="1" ChildAtt2="2"/>
      </Extn>
   </Root>
</RootList>