使用XSLT从xml文档打印包含属性的元素列表

使用XSLT从xml文档打印包含属性的元素列表,xml,xslt,Xml,Xslt,我需要解决一个很奇怪的问题。我需要一个XSLT样式表,用于打印结构未知的xml文档的元素及其属性列表。经过多次尝试,我终于创造了这样一个东西: <?xml version="1.0" encoding="ISO-8859-1"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:template match="/"> <HTML&

我需要解决一个很奇怪的问题。我需要一个XSLT样式表,用于打印结构未知的xml文档的元素及其属性列表。经过多次尝试,我终于创造了这样一个东西:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<HTML>
<title></title>
<body>  

<xsl:call-template name="recurs">
<xsl:with-param name="nextnodes" select="child::*" />
</xsl:call-template>

</body>
</HTML>
</xsl:template>

<xsl:template name="recurs">
<xsl:param name="nextnodes" />
<xsl:for-each select="$nextnodes">
<xsl:if test="not(name(current())=name(following::*)) and  not(name(current())=name(following::*/descendant::*)) ">
    Element <b><xsl:value-of select="name(current())" /></b> has attributes <text> </text>
    <xsl:for-each select="@*">
    <xsl:if test="position()=last()">
    <b><xsl:value-of select="name(current())" /><text>.</text></b>
    </xsl:if>
    <xsl:if test="position()!=last()">
        <b><xsl:value-of select="name(current())" /><text>,  </text></b>
    </xsl:if>
    </xsl:for-each>
    <br /><br />
</xsl:if>
<xsl:call-template name="recurs">
    <xsl:with-param name="nextnodes" select="child::*" />
</xsl:call-template>

</xsl:for-each> 
</xsl:template>

</xsl:stylesheet>

元素具有属性
.
,  


对于这种测试用例,当元素手册再次出现在其他元素中时,它可以正常工作,不过:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="task3_4a.xsl"?>
<catalog subnodes="2">

<cities country="England">
<city name="London" region="London" population="10000" />
<city name="New South Wales" region="Wales" population="800000" />

</cities> 

<articles country="USA">
<article name="My lovely country" src="art1.txt" />
<article name="Places to visit" src="art2.txt" />
<article name="Article 3" src="art3.txt" />
</articles>

<books>
<book title="Warhammer">
</book>
<book title="We fought for truth"> 
</book>
</books>

<scientifics  atr = " ">
<book title="Warhammer">
</book> 
</scientifics>
</catalog>

但当我尝试另一个测试时,在书中使用元素文章,它无法正确管理xml:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="task3_4a.xsl"?>
<catalog subnodes="2">

<cities country="England">
<city name="London" region="London" population="10000" />
<city name="New South Wales" region="Wales" population="800000" />

</cities> 

<articles country="USA">
<article name="My lovely country" src="art1.txt" />
<article name="Places to visit" src="art2.txt" />
<article name="Article 3" src="art3.txt" />
</articles>

<books>
<book title="Warhammer">
<article name="My lovely country" src="art1.txt" /> 
</book>
<book title="We fought for truth"> 
<article name="My lovely country" src="art1.txt" /> 
</book>
</books>

<scientifics  atr = " ">
<book title="Warhammer">

<article name="My lovely country" src="art1.txt" /> 
</book> 

</scientifics>

</catalog>


输出现在包含字符串“Element article has attributes name,src.”3次。我也不知道如何修复它

您遇到的一个问题是使用此XPath

<xsl:if test="not(name(current())=name(following::*)) ...

I.这里是一个非常简短而简单的XSLT 2.0解决方案

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

 <xsl:template match="/">
    <xsl:for-each-group select="//*"
         group-by="string-join((name(), @*/name()), '|')">
      <xsl:sort select="name()"/>

      <p>
        Element <b><xsl:sequence select="name()"/></b>
        has attributes: <xsl:value-of select="@*/name()" separator=", "/>
      </p>
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
<catalog subnodes="2">
    <cities country="England">
        <city name="London" region="London" population="10000" />
        <city name="New South Wales" region="Wales" population="800000" />
    </cities>
    <articles country="USA">
        <article name="My lovely country" src="art1.txt" />
        <article name="Places to visit" src="art2.txt" />
        <article name="Article 3" src="art3.txt" />
    </articles>
    <books>
        <book title="Warhammer">
            <article name="My lovely country" src="art1.txt" />
        </book>
        <book title="We fought for truth">
            <article name="My lovely country" src="art1.txt" />
        </book>
    </books>
    <scientifics  atr = " ">
        <book title="Warhammer">
            <article name="My lovely country" src="art1.txt" />
        </book>
    </scientifics>
</catalog>
<p>
        Element <b>article</b>
        has attributes: name, src</p>
<p>
        Element <b>articles</b>
        has attributes: country</p>
<p>
        Element <b>book</b>
        has attributes: title</p>
<p>
        Element <b>books</b>
        has attributes: </p>
<p>
        Element <b>catalog</b>
        has attributes: subnodes</p>
<p>
        Element <b>cities</b>
        has attributes: country</p>
<p>
        Element <b>city</b>
        has attributes: name, region, population</p>
<p>
        Element <b>scientifics</b>
        has attributes: atr</p>
<p>
        Element <b>article</b>
        has attributes: name src </p>
<p>
        Element <b>articles</b>
        has attributes: country </p>
<p>
        Element <b>book</b>
        has attributes: title </p>
<p>
        Element <b>books</b>
        has attributes: </p>
<p>
        Element <b>catalog</b>
        has attributes: subnodes </p>
<p>
        Element <b>cities</b>
        has attributes: country </p>
<p>
        Element <b>city</b>
        has attributes: name population region </p>
<p>
        Element <b>scientifics</b>
        has attributes: atr </p>


元素
具有以下属性:

当此转换应用于提供的XML文档时

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

 <xsl:template match="/">
    <xsl:for-each-group select="//*"
         group-by="string-join((name(), @*/name()), '|')">
      <xsl:sort select="name()"/>

      <p>
        Element <b><xsl:sequence select="name()"/></b>
        has attributes: <xsl:value-of select="@*/name()" separator=", "/>
      </p>
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
<catalog subnodes="2">
    <cities country="England">
        <city name="London" region="London" population="10000" />
        <city name="New South Wales" region="Wales" population="800000" />
    </cities>
    <articles country="USA">
        <article name="My lovely country" src="art1.txt" />
        <article name="Places to visit" src="art2.txt" />
        <article name="Article 3" src="art3.txt" />
    </articles>
    <books>
        <book title="Warhammer">
            <article name="My lovely country" src="art1.txt" />
        </book>
        <book title="We fought for truth">
            <article name="My lovely country" src="art1.txt" />
        </book>
    </books>
    <scientifics  atr = " ">
        <book title="Warhammer">
            <article name="My lovely country" src="art1.txt" />
        </book>
    </scientifics>
</catalog>
<p>
        Element <b>article</b>
        has attributes: name, src</p>
<p>
        Element <b>articles</b>
        has attributes: country</p>
<p>
        Element <b>book</b>
        has attributes: title</p>
<p>
        Element <b>books</b>
        has attributes: </p>
<p>
        Element <b>catalog</b>
        has attributes: subnodes</p>
<p>
        Element <b>cities</b>
        has attributes: country</p>
<p>
        Element <b>city</b>
        has attributes: name, region, population</p>
<p>
        Element <b>scientifics</b>
        has attributes: atr</p>
<p>
        Element <b>article</b>
        has attributes: name src </p>
<p>
        Element <b>articles</b>
        has attributes: country </p>
<p>
        Element <b>book</b>
        has attributes: title </p>
<p>
        Element <b>books</b>
        has attributes: </p>
<p>
        Element <b>catalog</b>
        has attributes: subnodes </p>
<p>
        Element <b>cities</b>
        has attributes: country </p>
<p>
        Element <b>city</b>
        has attributes: name population region </p>
<p>
        Element <b>scientifics</b>
        has attributes: atr </p>

生成所需的正确结果

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

 <xsl:template match="/">
    <xsl:for-each-group select="//*"
         group-by="string-join((name(), @*/name()), '|')">
      <xsl:sort select="name()"/>

      <p>
        Element <b><xsl:sequence select="name()"/></b>
        has attributes: <xsl:value-of select="@*/name()" separator=", "/>
      </p>
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
<catalog subnodes="2">
    <cities country="England">
        <city name="London" region="London" population="10000" />
        <city name="New South Wales" region="Wales" population="800000" />
    </cities>
    <articles country="USA">
        <article name="My lovely country" src="art1.txt" />
        <article name="Places to visit" src="art2.txt" />
        <article name="Article 3" src="art3.txt" />
    </articles>
    <books>
        <book title="Warhammer">
            <article name="My lovely country" src="art1.txt" />
        </book>
        <book title="We fought for truth">
            <article name="My lovely country" src="art1.txt" />
        </book>
    </books>
    <scientifics  atr = " ">
        <book title="Warhammer">
            <article name="My lovely country" src="art1.txt" />
        </book>
    </scientifics>
</catalog>
<p>
        Element <b>article</b>
        has attributes: name, src</p>
<p>
        Element <b>articles</b>
        has attributes: country</p>
<p>
        Element <b>book</b>
        has attributes: title</p>
<p>
        Element <b>books</b>
        has attributes: </p>
<p>
        Element <b>catalog</b>
        has attributes: subnodes</p>
<p>
        Element <b>cities</b>
        has attributes: country</p>
<p>
        Element <b>city</b>
        has attributes: name, region, population</p>
<p>
        Element <b>scientifics</b>
        has attributes: atr</p>
<p>
        Element <b>article</b>
        has attributes: name src </p>
<p>
        Element <b>articles</b>
        has attributes: country </p>
<p>
        Element <b>book</b>
        has attributes: title </p>
<p>
        Element <b>books</b>
        has attributes: </p>
<p>
        Element <b>catalog</b>
        has attributes: subnodes </p>
<p>
        Element <b>cities</b>
        has attributes: country </p>
<p>
        Element <b>city</b>
        has attributes: name population region </p>
<p>
        Element <b>scientifics</b>
        has attributes: atr </p>

元素文章
具有以下属性:name,src

元素文章 具有以下属性:国家

元素书 具有以下属性:title

元素书 具有以下属性:

元素目录 具有属性:子节点

元素城市 具有以下属性:国家

元素城市 具有以下属性:名称、区域、人口

元素科学 具有以下属性:atr

并在浏览器中显示为

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

 <xsl:template match="/">
    <xsl:for-each-group select="//*"
         group-by="string-join((name(), @*/name()), '|')">
      <xsl:sort select="name()"/>

      <p>
        Element <b><xsl:sequence select="name()"/></b>
        has attributes: <xsl:value-of select="@*/name()" separator=", "/>
      </p>
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
<catalog subnodes="2">
    <cities country="England">
        <city name="London" region="London" population="10000" />
        <city name="New South Wales" region="Wales" population="800000" />
    </cities>
    <articles country="USA">
        <article name="My lovely country" src="art1.txt" />
        <article name="Places to visit" src="art2.txt" />
        <article name="Article 3" src="art3.txt" />
    </articles>
    <books>
        <book title="Warhammer">
            <article name="My lovely country" src="art1.txt" />
        </book>
        <book title="We fought for truth">
            <article name="My lovely country" src="art1.txt" />
        </book>
    </books>
    <scientifics  atr = " ">
        <book title="Warhammer">
            <article name="My lovely country" src="art1.txt" />
        </book>
    </scientifics>
</catalog>
<p>
        Element <b>article</b>
        has attributes: name, src</p>
<p>
        Element <b>articles</b>
        has attributes: country</p>
<p>
        Element <b>book</b>
        has attributes: title</p>
<p>
        Element <b>books</b>
        has attributes: </p>
<p>
        Element <b>catalog</b>
        has attributes: subnodes</p>
<p>
        Element <b>cities</b>
        has attributes: country</p>
<p>
        Element <b>city</b>
        has attributes: name, region, population</p>
<p>
        Element <b>scientifics</b>
        has attributes: atr</p>
<p>
        Element <b>article</b>
        has attributes: name src </p>
<p>
        Element <b>articles</b>
        has attributes: country </p>
<p>
        Element <b>book</b>
        has attributes: title </p>
<p>
        Element <b>books</b>
        has attributes: </p>
<p>
        Element <b>catalog</b>
        has attributes: subnodes </p>
<p>
        Element <b>cities</b>
        has attributes: country </p>
<p>
        Element <b>city</b>
        has attributes: name population region </p>
<p>
        Element <b>scientifics</b>
        has attributes: atr </p>
元素文章 具有以下属性:name,src

元素文章 具有以下属性:国家

元素书 具有以下属性:title

元素书 具有以下属性:

元素目录 具有属性:子节点

元素城市 具有以下属性:国家

元素城市 具有以下属性:名称、区域、人口

元素科学 具有以下属性:atr

II。XSLT 1.0(双过程)解决方案:

<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 omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kElByNameandAttrs" match="*"
  use="concat(name(), '|', @_____attribs)"/>

 <xsl:variable name="vrtfPass1">
  <xsl:apply-templates/>
 </xsl:variable>

 <xsl:template match="*">
  <xsl:copy>
   <xsl:attribute name="_____attribs">
     <xsl:for-each select="@*">
       <xsl:sort select="name()"/>

       <xsl:value-of select="concat(name(), ' ')"/>
     </xsl:for-each>
   </xsl:attribute>

   <xsl:apply-templates select="*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="/">
   <xsl:apply-templates mode="pass2" select=
   "ext:node-set($vrtfPass1)//*
          [generate-id()
          =
           generate-id(key('kElByNameandAttrs',
                           concat(name(),
                                  '|',
                                  @_____attribs)
                           )
                            [1])
           ]"
   >
    <xsl:sort select="name()"/>
   </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="*" mode="pass2">
  <p>
        Element <b><xsl:value-of select="name()"/></b>
        has attributes: <xsl:value-of select="@_____attribs"/></p>
 </xsl:template>

</xsl:stylesheet>


元素
具有以下属性:

当XSLT 1.0转换应用于同一XML文档(如上)时,同样会产生所需的正确结果

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

 <xsl:template match="/">
    <xsl:for-each-group select="//*"
         group-by="string-join((name(), @*/name()), '|')">
      <xsl:sort select="name()"/>

      <p>
        Element <b><xsl:sequence select="name()"/></b>
        has attributes: <xsl:value-of select="@*/name()" separator=", "/>
      </p>
  </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>
<catalog subnodes="2">
    <cities country="England">
        <city name="London" region="London" population="10000" />
        <city name="New South Wales" region="Wales" population="800000" />
    </cities>
    <articles country="USA">
        <article name="My lovely country" src="art1.txt" />
        <article name="Places to visit" src="art2.txt" />
        <article name="Article 3" src="art3.txt" />
    </articles>
    <books>
        <book title="Warhammer">
            <article name="My lovely country" src="art1.txt" />
        </book>
        <book title="We fought for truth">
            <article name="My lovely country" src="art1.txt" />
        </book>
    </books>
    <scientifics  atr = " ">
        <book title="Warhammer">
            <article name="My lovely country" src="art1.txt" />
        </book>
    </scientifics>
</catalog>
<p>
        Element <b>article</b>
        has attributes: name, src</p>
<p>
        Element <b>articles</b>
        has attributes: country</p>
<p>
        Element <b>book</b>
        has attributes: title</p>
<p>
        Element <b>books</b>
        has attributes: </p>
<p>
        Element <b>catalog</b>
        has attributes: subnodes</p>
<p>
        Element <b>cities</b>
        has attributes: country</p>
<p>
        Element <b>city</b>
        has attributes: name, region, population</p>
<p>
        Element <b>scientifics</b>
        has attributes: atr</p>
<p>
        Element <b>article</b>
        has attributes: name src </p>
<p>
        Element <b>articles</b>
        has attributes: country </p>
<p>
        Element <b>book</b>
        has attributes: title </p>
<p>
        Element <b>books</b>
        has attributes: </p>
<p>
        Element <b>catalog</b>
        has attributes: subnodes </p>
<p>
        Element <b>cities</b>
        has attributes: country </p>
<p>
        Element <b>city</b>
        has attributes: name population region </p>
<p>
        Element <b>scientifics</b>
        has attributes: atr </p>

元素文章
具有以下属性:name src

元素文章 具有以下属性:国家

元素书 具有以下属性:title

元素书 具有以下属性:

元素目录 具有属性:子节点

元素城市 具有以下属性:国家

元素城市 具有属性:名称填充区域

元素科学 具有以下属性:atr


它向下遍历3个可能的节点层次结构,以到达节点。这就是为什么它会显示3次。您需要跟踪以某种方式找到的结构,然后进行比较,以确保您没有重复。1.2.3.是否需要将每个唯一元素的属性打印出来?还是所有元素?我需要打印文档中的所有元素及其属性,但尽管某些元素在文档中的不同层次上多次出现,对于任何此类元素,输出列表中应该只有一项。@ferbolg对于必须累积并与以前的值进行比较的操作类型(仅查看是否已显示),XSLT可能不是最佳解决方案。XSLT在格式化和转换方面非常好,但在计算和比较方面,使用带有映射/字典支持的脚本语言可能会更好。我现在意识到某种DOM或SAX解析可能会更好,但问题是我需要一个XSLT样式表…@Dimitri Novatchev非常好的解决方案+1。请您解释一下:group by=“string join((name(),@*/name()),“|”)”>?据我所知,您是按名称和所有属性分组的吗?XSLT 1.0中的muenchian分组也可以做到这一点吗?@FailedDev:Re:
groupby=“string join((name(),@*/name()),“|”)”
。这通过一个字符串进行分组,该字符串是元素名称及其所有属性名称的串联——所有属性都由一个管道字符连接。顺便说一句,我还添加了一个XSLT1.0解决方案@迪米特里·诺瓦切夫:很高兴学到新东西。