Как фильтровать узлы с определенным дочерним узлом - PullRequest
3 голосов
/ 20 апреля 2011

У меня есть эта таблица стилей 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 ]

2 голосов
/ 20 апреля 2011

Ваш тест <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 будет обработан 3 раза в режиме "foo". Может быть, вы имели в виду, что первый шаблон будет

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

Мне также нравится помещать явный select="*" в apply-шаблоны, просто чтобы было легче увидеть, что происходит. Но это вопрос предпочтений.

1 голос
/ 21 апреля 2011

Я пытаюсь найти узлы, которые содержат «a» дочерний элемент (и в конечном итоге тот, который содержит id = ".." атрибут).

У вас беспорядок режимов - это совершенно не имеет отношения к вашему вопросу.

Этот образец совпадения

*[a and @id]

соответствует любому дочернему элементу текущего узла (когда выполняется соответствующий <xsl:apply-templates>), который сам имеет дочерний элемент a, а также имеет атрибут id.

Этот образец совпадения:

*[a and @id='someString']

соответствует любому дочернему элементу текущего узла (когда выполняется соответствующий <xsl:apply-templates>), который сам имеет дочерний a, а также имеет атрибут id со значением 'someString'.

1 голос
/ 20 апреля 2011

Редактировать [устранены вводящие в заблуждение, неправильные части кода]

, так как нет входного документа и нет желаемого вывода, работает в соответствии с вашим xsl выше, и предположение:

Вам нужно по-разному находить / обрабатывать все узлы, которые

  • содержат a теги ==> foobar,
  • содержат a теги с атрибутом id ==> has-a-with-id,
  • являются тегами *, все остальные ==> они должны быть просто скопированы.

Так что если у вас есть входной 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>

Мне также было бы интересно узнать, как оптимизировать этот код, поэтому, если у кого-то есть идея, пожалуйста, не стесняйтесь поделиться /редактировать.

0 голосов
/ 22 апреля 2011

Ну, кто-то на канале #xml в Freenode помог мне написать эту альтернативную таблицу стилей, которая работает лучше:

<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>

Часть с ""может быть безопасно проигнорировано, потому что я добавил его позже, чтобы исправить проблему.

Что касается вывода, который мне потребовался для обработки, это стандартный XHTML, сгенерированный DocBook / XML, который имеет некоторое

/ теги с пустыми элементами &; lt; a id = "my_anchor_here /> для якорей вместо того, чтобы делать правильные вещи дляпоэтому я пытаюсь его отфильтровать. Вот отдельный образец: <?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>

...