2013-04-22 77 views
1

一致我有像這樣化妝屬性爲所有元素

<Elem1 Attrib1="1" Attrib2="2"/> 
<Elem2 Attrib1="21" Attrib3="23"/> 
<Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/> 

我希望讓所有的元素都有這樣

相同數量的屬性來改變這個文件中的所有元素不一致屬性的XML文件
<Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/> 
<Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4=""/> 
<Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34"/> 

這可以通過XSLT來實現嗎?

+0

我認爲,這是可能的。你有什麼試過的?你受到了什麼打擊? – 2013-04-22 06:44:45

回答

0

這是XSLT 1.0中的一種通用方法。它包含了一些額外的邏輯,以確保各項屬性均在同一順序:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes" /> 
    <xsl:key name="kAttr" match="@*" use="name()" /> 
    <xsl:variable name="distinctAttr" 
       select="//@*[generate-id() = 
          generate-id(key('kAttr', name())[1])]" /> 

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

    <xsl:template match="*/*"> 
    <xsl:copy> 
     <xsl:apply-templates select="$distinctAttr | @*"> 
     <xsl:sort select="name()" /> 
     <xsl:with-param name="parent" select="." /> 
     </xsl:apply-templates> 
     <xsl:apply-templates select="node()" /> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="@*"> 
    <xsl:param name="parent" select="/.." /> 
    <xsl:if test="not($parent) or 
        count(.. | $parent) = 1 or 
        not($parent/@*[name() = name(current())])"> 
     <xsl:attribute name="{name()}"> 
     <xsl:value-of select="substring(., 1, string-length() * 
               (2 - count($parent | ..)))"/> 
     </xsl:attribute> 
    </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

當此輸入運行:

<doc> 
    <Elem1 Attrib1="1" Attrib2="2"/> 
    <Elem2 Attrib1="21" Attrib3="23"/> 
    <Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/> 
</doc> 

結果是:

<doc> 
    <Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4="" /> 
    <Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4="" /> 
    <Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34" /> 
</doc> 
0

當轉換

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

<xsl:template match="Elem1|Elem2|Elem3"> 
<xsl:copy> 
<xsl:if test="@Attrib1"><xsl:attribute name="Attrib1"><xsl:value-of select="@Attrib1"/></xsl:attribute></xsl:if> 
<xsl:if test="not(@Attrib1)"><xsl:attribute name="Attrib1"></xsl:attribute></xsl:if> 
<xsl:if test="@Attrib2"><xsl:attribute name="Attrib2"><xsl:value-of select="@Attrib2"/></xsl:attribute></xsl:if> 
<xsl:if test="not(@Attrib2)"><xsl:attribute name="Attrib2"></xsl:attribute></xsl:if> 
<xsl:if test="@Attrib3"><xsl:attribute name="Attrib3"><xsl:value-of select="@Attrib3"/></xsl:attribute></xsl:if> 
<xsl:if test="not(@Attrib3)"><xsl:attribute name="Attrib3"></xsl:attribute></xsl:if> 
<xsl:if test="@Attrib4"><xsl:attribute name="Attrib4"><xsl:value-of select="@Attrib4"/></xsl:attribute></xsl:if> 
<xsl:if test="not(@Attrib4)"><xsl:attribute name="Attrib4"></xsl:attribute></xsl:if> 
</xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

下面XML運行

<test> 
<Elem1 Attrib1="1" Attrib2="2"/> 
<Elem2 Attrib1="21" Attrib3="23"/> 
<Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/> 
</test> 

給出所需的輸出

<?xml version='1.0' ?> 
<test> 
<Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/> 
<Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4=""/> 
<Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34"/> 
</test> 
1

有很多可能的描述。 這裏一點點簡單的一個,假設你有關的就是衆所周知的屬性列表:

<?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="Elem1|Elem2|Elem3"> 
     <xsl:copy > 
      <xsl:attribute name="Attrib1"> 
       <xsl:value-of select="@Attrib1"/> 
      </xsl:attribute> 
      <xsl:attribute name="Attrib2"> 
       <xsl:value-of select="@Attrib2"/> 
      </xsl:attribute> 
      <xsl:attribute name="Attrib3"> 
       <xsl:value-of select="@Attrib3"/> 
      </xsl:attribute> 
      <xsl:attribute name="Attrib4"> 
       <xsl:value-of select="@Attrib4"/> 
      </xsl:attribute> 
     </xsl:copy> 

    </xsl:template> 
    <xsl:template match="*"> 
     <test> 
     <xsl:apply-templates /> 
     </test> 
    </xsl:template> 

</xsl:stylesheet> 
2

下面是一個XSLT 2.0選項。它可能會被修改爲適用於XSLT 1.0。

XML輸入

<doc> 
    <Elem1 Attrib1="1" Attrib2="2"/> 
    <Elem2 Attrib1="21" Attrib3="23"/> 
    <Elem3 Attrib2="32" Attrib3="33" Attrib4="34"/> 
</doc> 

XSLT 2.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="attrs" select="//@*/name()"/> 
    <xsl:key name="kAttrs" match="@*" use="name()"/> 

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

    <xsl:template match="*[@*]"> 
     <xsl:copy> 
      <xsl:for-each select="key('kAttrs',$attrs)"> 
       <xsl:attribute name="{name(.)}"/> 
      </xsl:for-each> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

輸出

<doc> 
    <Elem1 Attrib1="1" Attrib2="2" Attrib3="" Attrib4=""/> 
    <Elem2 Attrib1="21" Attrib2="" Attrib3="23" Attrib4=""/> 
    <Elem3 Attrib1="" Attrib2="32" Attrib3="33" Attrib4="34"/> 
</doc> 

這裏的另一個XSLT 2.0選項,只會是2.0(這個人是MUCH也更快):

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
    <xsl:output indent="yes"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:variable name="attrs" select="distinct-values(//@*/name())"/> 

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

    <xsl:template match="*[@*]"> 
     <xsl:copy> 
      <xsl:for-each select="$attrs"> 
       <xsl:attribute name="{.}"/> 
      </xsl:for-each> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

這將返回相同的結果比(w /相同的輸入)。

+0

這是一個棘手的問題。添加所有具有空值的屬性,並將其替換爲現有的屬性。我喜歡。;-) – 2013-04-22 07:23:29

+0

@ hr_117 - 謝謝:-) – 2013-04-22 07:26:22

+0

我得到以下「錯誤預期的表達式結束,找到'('」在行「」 – user2071531 2013-04-24 05:18:26