2012-01-02 155 views
2

很抱歉,如果這已經討論過,但可以NT找到一個合適的回答我的問題..... 我有這樣的XML:過濾器屬性中使用基於屬性名稱XSLT

<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 \ r oot \ Extn \ @ ExtnAtt2是不需要的屬性。

感謝 等待您的回覆.... :)

乾杯

做到這一點
+0

如果你知道哪些屬性「額外」的,那麼你還知道哪些屬性是「沒有額外的」 =所需的,對不對?所以你可以使用' 2012-01-02 09:27:05

回答

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> 

的替代方法,如果你需要的話保持多個屬性的分機元件上,是用象一個樣式表,從而,其顯式列出的屬性,以保持:

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

注意,所有其它元件,除了分機元件,不受影響。

+0

感謝Tim,但是如果有多個屬性保留並刪除Extn標籤中的其餘部分,可以應用它。例如:假設xml看起來像: <子ChildAtt1 =」 1" ChildAtt2 = 「2」/> 和所需的XML是: <根RootAtt1 = 「1」 RootAtt2 = 「2」 RootAtt3 =」 3「> 2012-01-02 11:27:57

+0

@SMA_JAVA:不,Tim的解決方案假設'Extn '必須只有一個具有確切名稱的屬性。看到我的答案是一個完全通用的解決方案,它可以與任何數量的屬性一起工作,這些屬性的名稱我們事先不知道。 – 2012-01-02 18:14:38

+0

@SMA_JAVA:我已經擴展了我的答案來應對這個新要求。 – 2012-01-03 08:16:19

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

這使用推式樣式模板,您可以更改屬性或添加額外的模板以適應。 – Treemonkey 2012-01-02 10:26:36

0

這裏是一個真正解決方案,不同於目前公認的一個工作與「嚴」文件的元素的任何數量的屬性:

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