XSLT: сделать дочерний узел родным из контекстного узла - PullRequest
2 голосов
/ 01 марта 2011

выполнил поиск по этому вопросу и не нашел ответа, так что вот так ...

У меня есть xml, похожий на следующее:

<?xml version="1.0" encoding="utf-8"?>
<footnote ref="1">
    <para>Here is some text about some guy who made
        <emphasis role="italic">fascinating</emphasis> comment I want to quote
        <blockquote> So I went to this place and met this guy....</blockquote>
        It seemed more interesting at the time.
    </para>
</footnote>

Я хочу использовать xslt, чтобы изменить его на новую схему (используя новый префикс пространства имен)

<?xml version="1.0" encoding="utf-8"?>
<nns:footnote ref="1">
    <nns:fn-para>Here is some text about some guy who made
        <nns:emph type="it">fascinating</nns:emph> comment I want to quote:
    </nns:fn-para>
    <nns:fn-blockquote>
        <nns:bq-para>So I went to this place and met this guy....</nns:bq-para>
    </nns:fn-blockquote>
    <nns:fn-para> It seemed more interesting at the time.</nns:fn-para>
</nns:footnote>

Я попробовал несколько вещей ... взяв абзац, являющийся потомком сноски, и просматривая дочерние элементы, но это проблематично, потому что это не только текстовые узлы в абзаце, есть также тэги emph, и я до сих пор не знаю, как поместить дочерний узел вверх по дереву и снова в результирующее дерево ... это имеет смысл?

1 Ответ

3 голосов
/ 01 марта 2011

РЕДАКТИРОВАТЬ : Небольшой рефакторинг и расширенное объяснение.

Эта таблица стилей:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:nns="nns">
    <xsl:key name="kNodeByPrecedingBlock"
             match="para/node()[not(self::blockquote)]"
             use="generate-id(
                     (..|preceding-sibling::*[self::blockquote][1])[last()]
                  )"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="footnote">
        <nns:footnote>
            <xsl:apply-templates select="node()|@*"/>
        </nns:footnote>
    </xsl:template>
    <xsl:template match="para">
        <xsl:apply-templates select=".|blockquote" mode="group"/>
    </xsl:template>
    <xsl:template match="emphasis">
        <nns:emph>
            <xsl:apply-templates select="node()|@*"/>
        </nns:emph>
    </xsl:template>
    <xsl:template match="emphasis/@role">
        <xsl:attribute name="type">
            <xsl:value-of select="substring(.,1,2)"/>
        </xsl:attribute>
    </xsl:template>
    <xsl:template match="blockquote">
        <nns:fn-blockquote>
            <nns:bq-para>
                <xsl:apply-templates/>
            </nns:bq-para>
        </nns:fn-blockquote>
    </xsl:template>
    <xsl:template match="para" mode="group" name="makePara">
        <xsl:variable name="vGroup"
             select="key('kNodeByPrecedingBlock',generate-id())"/>
        <xsl:if test="$vGroup">
            <nns:fn-para>
                <xsl:apply-templates select="$vGroup"/>
            </nns:fn-para>
        </xsl:if>
    </xsl:template>
    <xsl:template match="*" mode="group">
        <xsl:apply-templates select="."/>
        <xsl:call-template name="makePara"/>
    </xsl:template>
</xsl:stylesheet>

Вывод:

<nns:footnote ref="1" xmlns:nns="nns">
   <nns:fn-para>Here is some text about some guy who made 
      <nns:emph type="it">fascinating</nns:emph> comment I want to quote 
   </nns:fn-para>
   <nns:fn-blockquote>
      <nns:bq-para> So I went to this place and met this guy....</nns:bq-para>
   </nns:fn-blockquote>
   <nns:fn-para>         It seemed more interesting at the time. 
   </nns:fn-para>
</nns:footnote>

Примечание: правило идентификации для перезаписи (только для стиля, но это хороший шаблон).Четыре правила прямого преобразования, соответствующие footnote, emphasis, @role атрибутам emphasis и blockquote.Ключ группировки, соответствующий «inline» дочерним элементам para: генерирует id первого предшествующего элемента «block» или para parent.Правило группировки для para применения шаблонов к элементам self и "block" в режиме "group".Соответствие правилу para в режиме "group" (также называется makePara): вывести абзац, если существует группа с контекстным узлом , генерирующим идентификатор в качестве значения ключа.Правило, соответствующее любому элементу в режиме "group" (это будет любой элемент «блок»): применить шаблоны к self (режим «сброс») и вызвать makePara именованный шаблон.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...