使用XSLT从xml文档打印包含属性的元素列表
我需要解决一个很奇怪的问题。我需要一个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&
<?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解决方案@迪米特里·诺瓦切夫:很高兴学到新东西。