代码之家  ›  专栏  ›  技术社区  ›  Boldewyn

XSLT:如何获取所有已用名称空间的列表

  •  10
  • Boldewyn  · 技术社区  · 14 年前

    我正在编写一个XSLT1.0样式表来将多命名空间XML文档转换为HTML。在结果HTML的某个地方,我想列出文档中出现的所有名称空间。

    我想到了

    <xsl:for-each select="//*|//@*">
      <xsl:value-of select="namespace-uri(.)" />
    </xsl:for-each>
    

    但我当然会得到无数的复制品。所以我必须过滤我已经打印出来的东西。

    访问 //@xmlns:* xmlns: 命名空间)。

    2 回复  |  直到 14 年前
        1
  •  7
  •   user357812 user357812    14 年前

    另一个没有扩展功能:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:template match="*">
            <xsl:param name="pNamespaces" select="'&#xA;'"/>
            <xsl:variable name="vNamespaces">
                <xsl:variable name="vMyNamespaces">
                    <xsl:value-of select="$pNamespaces"/>
                    <xsl:for-each select="namespace::*
                                            [not(contains(
                                                     $pNamespaces,
                                                     concat('&#xA;',.,'&#xA;')))]">
                        <xsl:value-of select="concat(.,'&#xA;')"/>
                    </xsl:for-each>
                </xsl:variable>
                <xsl:variable name="vChildsNamespaces">
                    <xsl:apply-templates select="*[1]">
                        <xsl:with-param name="pNamespaces"
                                            select="$vMyNamespaces"/>
                    </xsl:apply-templates>
                </xsl:variable>
                <xsl:value-of select="concat(substring($vMyNamespaces,
                                                       1 div not(*)),
                                             substring($vChildsNamespaces,
                                                       1 div boolean(*)))"/>
            </xsl:variable>
            <xsl:variable name="vFollowNamespaces">
                <xsl:apply-templates select="following-sibling::*[1]">
                    <xsl:with-param name="pNamespaces" select="$vNamespaces"/>
                </xsl:apply-templates>
            </xsl:variable>
            <xsl:value-of
                 select="concat(substring($vNamespaces,
                                          1 div not(following-sibling::*)),
                                substring($vFollowNamespaces,
                                          1 div boolean(following-sibling::*)))"/>
        </xsl:template>
    </xsl:stylesheet>
    

    http://www.w3.org/XML/1998/namespace
    mynamespace
    mynamespace2
    mynamespace3
    

    :还有这个XPath表达式:

    //*/namespace::*[not(. = ../../namespace::*|preceding::*/namespace::*)]
    

    作为证明,此样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text"/>
        <xsl:template match="/">
            <xsl:for-each select="//*/namespace::*
                                         [not(. = ../../namespace::*|
                                                  preceding::*/namespace::*)]">
                <xsl:value-of select="concat(.,'&#xA;')"/>
            </xsl:for-each>
        </xsl:template>
    </xsl:stylesheet>
    

    输出:

    http://www.w3.org/XML/1998/namespace
    我的命名空间
    我的命名空间2
    

    此样式表:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text"/>
        <xsl:key name="kElemByNSURI"
                 match="*[namespace::*[not(. = ../../namespace::*)]]"
                  use="namespace::*[not(. = ../../namespace::*)]"/>
        <xsl:template match="/">
            <xsl:for-each select=
                "//namespace::*[not(. = ../../namespace::*)]
                               [count(..|key('kElemByNSURI',.)[1])=1]">
                <xsl:value-of select="concat(.,'&#xA;')"/>
            </xsl:for-each>
        </xsl:template>
    </xsl:stylesheet>
    

    输出:

    我的命名空间
    我的命名空间2
    

    编辑 5:在处理XSLT处理器时 namespace axe实现(如TransforMiix),只能提取实际用于此样式表的名称空间:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output method="text"/>
        <xsl:key name="kElemByNSURI" match="*|@*" use="namespace-uri()"/>
        <xsl:template match="/">
            <xsl:for-each select=
                "(//*|//@*)[namespace-uri()!='']
                           [count(.|key('kElemByNSURI',namespace-uri())[1])=1]">
                <xsl:value-of select="concat(namespace-uri(),'&#xA;')"/>
            </xsl:for-each>
        </xsl:template>
    </xsl:stylesheet>
    

    TransforMiix输出:

    mynamespace2
    
        2
  •  5
  •   Dimitre Novatchev    14 年前

    这种转变

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="text"/>
     <xsl:template match="/">
       <xsl:for-each select=
        "//namespace::*[not(. = ../../namespace::*)]">
         <xsl:value-of select="concat(.,'&#xA;')"/>
       </xsl:for-each>
     </xsl:template>
    </xsl:stylesheet>
    

    应用于此XML文档时 :

    <authors xmlns:user="mynamespace">
      <?ttt This is a PI ?>
      <author xmlns:user2="mynamespace2">
        <name idd="VH">Victor Hugo</name>
        <user2:name idd="VH">Victor Hugo</user2:name>
        <nationality xmlns:user3="mynamespace3">French</nationality>
      </author>
    </authors>
    

    http://www.w3.org/XML/1998/namespace
    mynamespace
    mynamespace2
    mynamespace3
    

    更新

    <authors xmlns:user="mynamespace">
      <?ttt This is a PI ?>
      <author xmlns:user2="mynamespace2">
        <name idd="VH">Victor Hugo</name>
        <user2:name idd="VH">Victor Hugo</user2:name>
        <nationality xmlns:user3="mynamespace3">French</nationality>
      </author>
      <t xmlns:user2="mynamespace2"/>
    </authors>
    

    命名空间 "mynamespace2" 产量将增加两倍。

    :

    <xsl:stylesheet version="1.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:ext="http://exslt.org/common"
     exclude-result-prefixes="ext">
     <xsl:output method="text"/>
    
     <xsl:key name="kNSbyURI" match="n" use="."/>
    
     <xsl:template match="/">
       <xsl:variable name="vrtfNS">
           <xsl:for-each select=
            "//namespace::*[not(. = ../../namespace::*)]">
             <n><xsl:value-of select="."/></n>
           </xsl:for-each>
       </xsl:variable>
    
       <xsl:variable name="vNS" select="ext:node-set($vrtfNS)/*"/>
    
       <xsl:for-each select=
        "$vNS[generate-id()
             =
              generate-id(key('kNSbyURI',.)[1])
             ]">
         <xsl:value-of select="concat(., '&#xA;')"/>
       </xsl:for-each>
     </xsl:template>
    </xsl:stylesheet>
    

    当此转换应用于上述XML文档时,它只生成文档中所有唯一的名称空间

    http://www.w3.org/XML/1998/namespace
    我的命名空间
    我的命名空间2
    

    第二部分:XSLT2.0解决方案 .

    distinct-values(//namespace::*)