如何使用某个子节点过滤节点

时间:2011-04-20 15:01:30

标签: xml xslt xpath xhtml xslt-1.0

我有这个XSLT样式表,我正在尝试查找包含a子元素的节点(最终包含id=".."属性的节点)。但是,无论我做什么,<xsl:when test="a">都不会匹配。 xsltproc永远不会匹配,并且此命令行无限期挂起,而只是始终发出getdateandtime

saxon9 lib/docbook/5/essays/foss-and-other-beasts-v3ll-in-one.xhtml bin/clean-up-docbook-xhtml-1.1.xslt

我在使用Mandriva Linux Cooker。这是我的样式表:

<xsl:stylesheet version = '1.0'
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xhtml="http://www.w3.org/1999/xhtml"
    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
    >

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"
        doctype-public="-//W3C//DTD XHTML 1.1//EN"
        doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
        />

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

    <xsl:template mode="copy_html_ns" match="*">
        <xsl:element xmlns="http://www.w3.org/1999/xhtml" 
                     name="{local-name()}">
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates mode="foo" />
       </xsl:element>
    </xsl:template>

    <xsl:template match="*" mode="foo">
        <xsl:choose>
            <xsl:when test="a">
                <xsl:element xmlns="http://www.w3.org/1999/xhtml" 
                             name="foobar">
                    <!--
                    <xsl:attribute name="id">
                        <xsl:value-of select="a[@id]" />
                    </xsl:attribute>
                    -->
                    <xsl:copy-of select="@*" />
                    <xsl:apply-templates mode="foo" />
                </xsl:element>
            </xsl:when>
            <xsl:when test="local-name() = 'a' and @id">
            </xsl:when>
            <xsl:otherwise>
                <xsl:element xmlns="http://www.w3.org/1999/xhtml" 
                             name="{local-name()}">
                    <xsl:copy-of select="@*" />
                    <xsl:apply-templates mode="foo" />
                </xsl:element>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>

4 个答案:

答案 0 :(得分:2)

您的测试<xsl:when test="a">是正确的,用于测试上下文节点是否具有名为a的任何子元素。

  

“然而,<xsl:when test="a">   无论我做什么都不会匹​​配。“

你怎么知道它永远不匹配?如果您提供样本输入,预期输出和实际输出,我们可以更好地诊断预期输出!=实际输出的原因。

你知道顺便提一下吗

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

会将模式“foo”模板应用于每个元素的所有子元素吗? (它将递归地将其应用于这些孩子的所有孩子)。所以如果你有一份文件

<w><x><y><z/></y></x></w>

然后元素z将以“foo”模式处理3次。 也许你的意思是第一个模板

<xsl:template match="/">
    <xsl:apply-templates mode="foo" />
</xsl:template>

我还想在apply-templates上添加一个明确的select="*",以便更容易看到正在发生的事情。但这是一个偏好问题。

答案 1 :(得分:1)

修改
[删除误导,错误的代码部分]

因为没有输入文档和没有所需的输出,所以通过上面的xsl工作,并假设:

您需要以不同的方式查找/处理所有

节点
  • 包含a个标签==&gt; foobar
  • 包含带有a属性的id代码==&gt; has-a-with-id
  • *个标签,所有其他标签==&gt;他们应该 被复制。

所以如果你有一个像

这样的输入xml
<?xml version="1.0"?>
<base>
    <some-child>
        <a>an a</a>
        <b>a b</b>
        <a>other a</a>
        <b>other b</b>
    </some-child>
    <some-child>
        <b>third b</b>
        <a id="blah">third a</a>
        <b>fourth b</b>
    </some-child>
    <some-child>
        <b>last b</b>
    </some-child>
</base>

你的输出应该是

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE base PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<base xmlns="http://www.w3.org/1999/xhtml">
    <foobar>
        <a>an a</a>
        <b>a b</b>
        <a>other a</a>
        <b>other b</b>
    </foobar>
    <has-a-with-id>
        <b>third b</b>
        <a id="blah">third a</a>
        <b>fourth b</b>
    </has-a-with-id>
    <some-child>
        <b>last b</b>
    </some-child>
</base>

如果是这种情况,我的解决方案就是

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" 
        xmlns:xhtml="http://www.w3.org/1999/xhtml" 
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" 
        doctype-public="-//W3C//DTD XHTML 1.1//EN" 
        doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/">
        <xsl:apply-templates mode="foo"/>
    </xsl:template>

    <xsl:template match="*[a[@id]]" mode="foo">
        <xsl:element xmlns="http://www.w3.org/1999/xhtml" name="has-a-with-id">
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates mode="foo"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="*[a[not(@id)]]" mode="foo">
        <xsl:element xmlns="http://www.w3.org/1999/xhtml" name="foobar">
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates mode="foo"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="*" mode="foo">
        <xsl:element xmlns="http://www.w3.org/1999/xhtml" name="{local-name()}">
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates mode="foo"/>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

我也很好奇如何优化这段代码,所以如果有人有想法,请随时分享/编辑。

答案 2 :(得分:1)

  

我正在尝试查找包含的节点   一个“a”子元素(最终   一个包含id =“..”的   属性)。

你的模式很混乱 - 这与你的问题完全无关。

此匹配模式

*[a and @id]

匹配当前节点的任何子节点(执行相应的<xsl:apply-templates>时),它本身有一个子级a,并且还具有id属性。

此匹配模式:

*[a and @id='someString']

匹配当前节点的任何子节点(当执行相应的<xsl:apply-templates>时),其本身具有子a并且还具有值为id的{​​{1}}属性。

答案 3 :(得分:0)

好吧,有人在Freenode的#xml频道帮助我编写了这个更好的替代样式表:

<xsl:stylesheet version = '1.0'
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:xhtml="http://www.w3.org/1999/xhtml"
    xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
    >

    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"
        doctype-public="-//W3C//DTD XHTML 1.1//EN"
        doctype-system="http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"
        />

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

    <xsl:template match="node()[xhtml:a/@id]">
        <xsl:copy>
            <xsl:copy-of select="xhtml:a/@id"/>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="xhtml:h3[@class='author']">
        <xsl:element name="h2">
            <xsl:copy-of select="xhtml:a/@id"/>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="xhtml:a/@id"/>

</xsl:stylesheet>

那里的部分有“&lt; xsl:template match =”xhtml:h3 [@ class ='author']“&gt;”可以安全地忽略,因为我稍后添加它来解决问题。

关于我需要处理的输出,它是由DocBook / XML生成的标准XHTML,其具有一些&lt; h2&gt;。 /&lt; h3&gt;标签为空&amp ;; lt; a id =“my_anchor_here /&gt;元素代表锚点,而不是为&lt; h2 id =”my_anchor_here“&gt;做正确的事情,所以我试图过滤它。

这是一个独立的样本:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><title>Open Source, Free Software and Other Beasts (version 3)</title><meta name="generator" content="DocBook XSL-NS Stylesheets V1.76.1"/><link rel="home" href="#index" title="Open Source, Free Software and Other Beasts (version 3)"/><link rel="next" href="#introduction" title="Introduction"/></head><body><div xml:lang="en-GB" class="article"><div class="titlepage"><div><div><h1 class="title"><a id="index"/>Open Source, Free Software and Other Beasts (version 3)</h1></div><div><div class="authorgroup"><div class="author"><h3 class="author"><span class="firstname">Shlomi</span> <span class="surname">Fish</span></h3><div class="affiliation"><div class="address"><p><br/>
                    <code class="email">&lt;<a class="email" href="mailto:shlomif@shlomifish.org">shlomif@shlomifish.org</a>&gt;</code><br/>
                    <code class="uri"><a class="uri" href="http://www.shlomifish.org/"/></code><br/>
                </p></div></div></div></div></div><div><p class="copyright">Copyright © 2004, 2006, 2011 Shlomi Fish</p></div><div><div class="legalnotice"><a id="main_legal_notice"/><p>

        This document is copyrighted by Shlomi Fish under the 
        <a class="link" href="http://creativecommons.org/licenses/by/3.0/">Creative
        Commons Attribution License (CC-by) version 3.0</a> (or at 
        your option a greater version).
    </p></div></div></div><hr/></div><div class="section"><div class="titlepage"><div><div><h2 class="title"><a id="introduction"/>Introduction</h2></div></div></div><p>
Many people will hear about Linux in the news, being the cool new operating
system that everyone can use free of charge. Those who become interested in
it enough or actually start working with it, will learn that it is made out
of many independent "open source" components. Now, after enough time
(perhaps very soon), they will learn that the term "free software" (where
free is free as in "free speech" and not free as in "free beer") can be
used as an alternative to the adjective "open source". But what is open
source and free software? What distinguishes them from other software that
is available to the public at no cost or is distributed as shareware?
</p><p>
Note that the terms "free software" and "open source" would be used
throughout this article to refer to the same phenomenon. I do not religiously
stick to either term.
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title"><a id="licences_and_proprietary_software"/>Software Licences and "Proprietary" Software</h2></div></div></div><p>
This section deals with the legal details of distributing software, and the
so-called licences that dictate what can be done with them.
</p><p>
Software out of being a sequence of bits, that can be transcribed to a
paper, spoken or otherwise transported is considered speech and so is
protected by the <a class="link" href="http://en.wikipedia.org/wiki/Freedom_of_speech">Freedom of Speech principle of Liberalism</a>. Thus, writing
software and distributing it are a constitutional right in most liberal
countries.
</p><p>
Nevertheless, a piece of software, as any other text, can be copyrighted.
Copyright involves making sure that the software as given to someone else
other than its originator or copyright holder will be restricted in use or
modification. An originator can outline what he believes to be a proper use
of the software in a code licence (which applies to the code) or an
"End-User License Agreement" (or EULA which applies to given binaries).
</p><p>
Proprietary software, i.e: such whose use, modification or distribution is
encumbered, was a relatively new phenomenon if you take a look at the old
history of computing. It actually started even before the time when
Microsoft, then a very small company wrote Altair Basic, and Bill Gates
published the famous (or possibly infamous) <a class="link" href="http://www.blinkenlights.com/classiccmp/gateswhine.html">"Open Letter to Altair Hobbyists"</a>. 
In fact, IBM and other companies distributed proprietary software for 
mainframe systems, a long time before the Personal Computer revolution.
</p><p>
The PC revolution, however, made the situation more critical. Soon,
computers became faster, more powerful, with larger memory, and more common
as time went by. At the moment, there are 100's of millions of Pentiums and
other computers out there, and millions of newer computers are sold each year.
</p><p>
Yet, the majority of these computers mostly run software that cannot be
modified or distributed, at least not effectively or legally. The free
software (or open-source) movement started as an anti-thesis to the
tendency of vendors to hide the details of their software from the public.
The Linux Operating System with its various components (most of which are
available to other systems as well, and are not affiliated with the Linux
kernel in particular) is the most visible showcase to this phenomena. By
installing Linux it is possible to turn an everyday personal computer into
a full fledged UNIX-based workstation or server, which is a 100% powerful GNU 
system. This can cost little if any money, and the various components of the 
operating system are all freely modifiable and can be re-distributed in their
modified form.
</p><p>
It is not the only place where free software can be used. It is in fact
possible to turn a Windows installation into a Linux-like GNU system as
well (see <a class="link" href="http://www.cygwin.com/">Cygwin</a> for instance) or run 
many native Microsoft Windows open-source programs on one's Windows 
installation.
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title"><a id="meaning_of_terms"/>Meaning of the terms</h2></div></div></div><p>
According to the <a class="link" href="http://www.gnu.org/philosophy/free-sw.html">Free Software Definition </a> free software must fulfill 4 freedoms:
</p><div class="orderedlist"><ol class="orderedlist"><li class="listitem"><p>
The freedom to run the program, for any purpose
</p></li><li class="listitem"><p>
The freedom to study how the program works, and adapt it to your needs.
Access to the source code is a precondition for this.
</p></li><li class="listitem"><p>
The freedom to redistribute copies so you can help your neighbour
</p></li><li class="listitem"><p>
The freedom to improve the program, and release your improvements to the
public, so that the whole community benefits . Access to the source code is
a precondition for this. 
</p></li></ol></div><p>
    The <a class="link" href="http://www.opensource.org/docs/definition_plain.php">Open Source definition</a> is similar, but some licences can qualify as 
    open-source and not as free
software. This is usually not an issue, because the majority of open source
software out there is free as well. Moreover, lately most of the companies
and people who have phrased their own software licences, have tried to also
get the Free Software Foundation to approve their licences as free software
in their eyes.
</p><p>
Despite common belief, selling free/open-source software is perfectly
legitimate. In fact, one can charge as much as he pleases for it.
Nevertheless, most free software is distributed for free or for very
cheaply on the Internet and other mediums. This is due to the fact that its
freely distributable nature does not give way much to sale value, so there
usually is no point in attempting to mandate a charge for selling it.
</p><p>
Another common misconception is that it sometimes cannot be modified or
customised for internal use. In fact, all free software (but not <span class="emphasis"><em>all</em></span>
open source software), can. Only when you wish to distribute it (free of
charge or commercially), you may have to distribute your changes.
(depending on the licence) The use of open source software to process
proprietary content or be processed by non-free programs is also, always
available. Thus, an open-source C compiler can be used to compile the code
of proprietary programs like the Oracle Database Server.
</p></div><div class="section"><div class="titlepage"><div><div><h2 class="title"><a id="history"/>History</h2></div></div></div><p>
This section is not a definitive overview of the history of the free
software movement. It focuses on the issues regarding the usage of the
common terms.
</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a id="history_unix_bsd"/>Early Days, AT&amp;T UNIX, BSD</h3></div></div></div><p>
The free software movement (before it was called this way) started
organically from individuals who distributed code they wrote under the
Public Domain or what would now be considered open source or semi-open
source licences. 
</p><p>
AT&amp;T UNIX that started at 1969 was the first showcase for this
movement. Several Bell Labs Engineers led by Ken Thompson developed UNIX
for their own use, and out of legal restrictions AT&amp;T faced, decided to
distribute it to academic organizations and other organizations free-of-charge
with the source included. (that licence did not qualify as open-source but
it was pretty close). UNIX eventually sported the C programming languages,
which enabled writing code that would run on many platforms easier, and the
UNIX sources included a C compiler that was itself written in C. Around the
early 70's the only computers capable of running UNIX were main-frames and
the so-called "mini-computers" so there initially weren't as many
installations as only large organizations could support buying computers to
deploy UNIX on. 
</p><p>
That changed as integrated circuits, and computers became cheaper and more
powerful. Very soon, cheap UNIX-based servers and workstations became
commonplace and the number of UNIX installations exploded. 
<sup>[<a id="present_day_unixes" href="#ftn.present_day_unixes" class="footnote">1</a>]</sup>
</p><p>
    Nadav Har'El has prepared <a class="link" href="http://groups.yahoo.com/group/hackers-il/message/1731">a coverage of the BSDs and early AT&amp;T UNIX
        history</a>.
</p><p>
The University of California at Berkeley (a.k.a UCB) forked its own version of 
AT&amp;T UNIX and started re-writing parts of the code, and incorporating many
changes of its own. The parts that the Berkeley developers wrote on their
own had originally been licensed UCB and kept as non-FOSS (= "free and open
source software") "All Rights Reserved" licence. The BSD system became very 
popular (perhaps even more than the AT&amp;T one).
</p><p>
When Arpanet, the predecessor to the Internet was disbanded due to inadequacy,
the Internet converted to running on top of 32-bit UNIX boxes such as
the <a class="link" href="http://en.wikipedia.org/wiki/VAX">VAX architecture by Digital
Equipment Corporation</a> (now part of Hewlett-Packard). This caused a 
merging of the UNIX culture with the Arpanet enthusiasts who exchanged code
on the Arpanet, and UNIX programmers started sharing code for various
components and add-ons of UNIX on the Internet.
</p></div></div></div></body></html>