Оценка оператора XPATH на основе динамической строки

(Вроде) Короткие и (может быть?) Сладкие

Как поставить условную логику (тот же XPATH, что и в <xsl:if>'stest атрибут) в атрибут листа XML, который читается через document('layoutsheet.xml') без использования saxon:evaluate или XSLT 3 <xsl:evaluate> на самом деле оценить логику в листе вызова XSL? (а также dyn:evaluate вроде бы тоже нет)


Пояснение: что я в основном ищу, так это если есть какой-либо шаблон, использующий представления логики и связанных преобразований узлов, который бы привел меня к аналогичному поведению. Я не против создания репрезентативной структуры на листе XML, которая обрабатывает поведение макета. Сейчас я просто рисую пробел во всем, что не могло бы перерасти в написание полноценного интерпретатора в XSL, что, вероятно, кажется ужасным дублированием усилий и пустой тратой времени на худшие результаты.

Поскольку я не вызываю синтаксический анализатор XSL (он вызывается программным обеспечением, которое я не поддерживаю и не могу напрямую изменить), я по сути ограничен тем, что является родным для Saxon. В основном я хочу получить портативный ответ как для нашей собственной будущей безопасности, так и для потенциального обмена, если он окажется ценным в другом месте. Если это лучшее, чем я собираюсь управлять с помощью имеющихся под рукой инструментов, я в порядке, услышав это.


В идеале мне бы хотелось, чтобы эта логика была полностью инкапсулирована в лист XML, а не полагаться на знание отдельных аспектов ее в листе XSL. То есть я не хочу предполагать, что это всегда будет сравнение из двух частей, использующее конкретный вызов функции для оценки отдельного элемента по отношению к значению (например, сохранение обеих сторон логической оценки в качестве отдельных атрибутов, которые мне тогда пришлось бы знаю, в листе XSL для оценки друг против друга не было бы идеально). Я также не хочу делать логику выбора совпадений на основе конкретной структуры макета: идея состоит в том, чтобы сделать ее как можно более независимой от структуры, и вместо этого включить соответствующую структурную логику в лист XML.

Хотя я мог бы загрузить лист XML с более глубокой структурой для использования в качестве сопоставляющих условий (что, в свою очередь, продолжало бы их структуру преобразования идентификаторов глубже, когда совпадение оценивается как истинное, или нет), в идеале я все же предпочел бы что-то гибкое, а не более сложное. условная логика, а не простой тест на равенство двух значений, такой как допускается полными операторами XPATH.


Более подробное объяснение и связанные фрагменты кода

Я работаю в CMS на основе XSLT и пытаюсь создать целевую систему с динамической версией, используя отдельный лист XML для определения макета документа. Пока что это была небольшая работа, но все идет хорошо. Короче говоря, нам нужно было нечто более динамичное во время выполнения, чем простое переопределение с помощью вложения import / include.

Первоначальная система основывалась на именованных шаблонных вызовах для перемещения по разным областям страницы, а затем преобразования идентификаторов для завершения, включая соответствующие части. Я по существу заменил это на лист компоновки XML, который использует шаблонные "вызовы" шаблонов, которые совпадают с моими XSL-листами. Это начальная итерация, предназначенная для максимально быстрой реализации, обеспечивая при этом большую гибкость в будущем, следовательно, оставаясь близкой к названной парадигме вызова.

Одна из проблем, с которой я столкнулся, заключается в том, как обрабатывать условное размещение без необходимости делать конкретные совпадения и соответствующие "вызовы" и присоединять связанную логику к моему листу XSL, вместо того, чтобы иметь возможность модульной логики из XML-кода.

Я нашел работающее в настоящее время решение с использованием saxon: define, но хотел бы получить информацию о других решениях (XSLT 2), которые не зависят от специфических расширений производителя. Поскольку это находится в сторонней CMS (OU Campi OmniUpdate), я не могу загружать расширения самостоятельно: я в основном застрял с тем, что уже загружено Saxon.

Базовая схема: (XML с XHTML для определения структуры документа, которая затем объединяется с помощью XSLT из листа вызывающего XML-документа, содержащего фактическое содержимое документа)

<mus:layoutsheet org="msu" version="2"
xmlns:mus="http://www.montana.edu/web/xsl/variables"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ou="http://omniupdate.com/XSL/Variables"
exclude-result-prefixes="xsl mus ou">

    <mus:call-template name="pre-processing-pub" />     
    <mus:call-template name="doctype" />
    <html>

        <mus:call-template name="pre-processing"/>

        <mus:call-template name="head" />
        <body class="responsive">
            <mus:call-template name="header" />

            <div class="container">
                <div class="row">
                    <mus:call-template name="titles-region" />
                    <mus:call-template name="breadcrumb" />
                </div>
            </div>

            <div class="container" id="content">

                <!-- this is the full width feature region -->
                <mus:call-template name="banners-region" cond="ou:pcfparam('full-width-feature-area') = 'show'"/>
                <!-- ok how do we do conditional placement? because this needs to get called in here or in content -->
                <!-- how about having that as an attribute here, then we can react to that in the match-->

                <div class="row">

                    <mus:call-template name="nested-nav" />
                    <!--wrap in an if statement for handling the different locations when tabbed -->                        
                    <div id="rightpane" class="col-xs-12 pull-right page-content sec">
                        <mus:call-template name="banners-region" cond="not(ou:pcfparam('full-width-feature-area') = 'show')"/>

                        <mus:call-template name="content" />


                    </div>                          

                    <mus:call-template name="contact-info" /> 

                </div>
            </div>
            <!--<xsl:call-template name="bottom-span-bar" />    -->

            <mus:call-template name="footer" />
        </body>
    </html>
</mus:layoutsheet>

Рассматриваемые элементы <mus:call-template name="banners-region" cond="ou:pcfparam('full-width-feature-area') = 'show'"/> а также <mus:call-template name="banners-region" cond="not(ou:pcfparam('full-width-feature-area') = 'show')"/>

@cond является атрибутом, загруженным с операторами XPATH, которые в противном случае были бы содержимым xsl:if Тест окружает этот шаблон "вызовом" в каждом конкретном случае.

Обратите внимание, что хотя в этой версии Saxon имеются элементы XSLT 3, включая <xsl:evaluate>Я столкнулся с проблемами пространства имен при попытке заставить это работать здесь с вызовом функции ou:pcfparam (все правильные пространства имен включены в лист вызова xsl, так что это не так). Хотя я мог бы покончить с вызовом функции и использовать чистый xpath, мне пришлось бы использовать //, чтобы избежать другой проблемы пространства имен с частью структуры связанного элемента, и на данный момент она тоже ломается (возможно, потому что она ссылается на элемент в XML-лист, на котором вызывается процесс преобразования, а не XML-лист, в котором хранится макет). Я также предпочел бы избегать XSLT 3, где это возможно, на данный момент, чтобы сохранить некоторые основные методологии, над которыми я работаю, более переносимыми.

Соответствующий соответствующий шаблон:

<xsl:template match="mus:call-template[@name='banners-region']">
    <xsl:if test="saxon:evaluate(@cond)">
        <xsl:call-template name="slider" /> 
    </xsl:if>
</xsl:template>

Я чувствую, что, может быть, я что-то здесь упустил, возможно, что-то, что в противном случае должно быть очевидным (может быть, потому что я пытаюсь не заболеть бронхитом, бла). Несмотря на то, что саксон: оценка прост в использовании, я предпочел бы что-то более переносимое, потому что этот подход в целом допускает некоторую очень хорошую модульность в соответствии с концепциями архитектуры MVC для обработки неструктурированных листов контента на основе XML с использованием относительно простого XHTML+. легкий лист макета XML для обработки большей части структуры представления и представления, облегчающий людям, не знакомым с XSLT, пересматривать связанную структуру.

Примечания: EXSLT dyn:valu не реализован в Saxon, так что это не является кросс-совместимым вариантом, хотя, если он функционально эквивалентен, тогда, я думаю, я могу придерживаться saxon:valuate и просто сказать людям заменить его на Dyn: оценивать, если не включен. саксон, который может быть лучшим способом пойти сюда.


Сокращенный пример формата фактически вызывающего XML-листа (я сократил количество элементов, но структура та же самая, это по сути параметры и связанный с ним информационный лист, и именно там редактор в CMS фактически сохраняет изменения):

<?xml version="1.0" encoding="utf-8"?>
<?pcf-stylesheet path="/multi-standard-new.xsl" site="XSL" extension="html"?>
<!DOCTYPE document SYSTEM "/data/staging/oucampus/MSU-Bozeman/XSL/_resources/dtd/standard.dtd">
<document xmlns:ouc="http://omniupdate.com/XSL/Variables">
    <parameter name="page-type">multi-feature</parameter>


    <ouc:properties label="metadata">
        <meta name="description" content="Description" />
        <meta name="keywords" content="Some keywords here" />
    </ouc:properties>


    <ouc:properties label="config">
        <title>The title</title>

        <!-- +++++++++++++++++++++++ -->
        <!-- Processing Instructions -->
        <!-- +++++++++++++++++++++++ -->

        <parameter
            name="page-subtitle"
            group="Everyone"
            type="checkbox"
            prompt="Show Subtitle"
            alt="Check to display the subtitle region."
        >
<option value="show" selected="false">Yes</option>
</parameter>
        <parameter section="Processing Instructions"
            name="page-preprocessing"
            group="tmplSettings_Processing"
            type="checkbox"
            prompt="Pre-processing"
            alt="Check to enable the pre-processing region. This region is for server side instructions which must run before any HTML."
        >
<option value="show" selected="true">Yes</option>
</parameter>
    </ouc:properties>
    <ouc:div label="page-subtitle"  group="Everyone"  button-class="oucEditButton" button-text="Subtitle" break="break" >
        <ouc:editor wysiwyg-class="page-subtitle" csspath="/_resources/ou/editor/maincontent.css" cssmenu="/_resources/ou/editor/menu.txt" width="955" />
Hark! A Subtitle!
    </ouc:div>
<ouc:div label="main-content"  group="Everyone"  button-class="oucEditButton" button-text="Main Content" break="break" ><ouc:editor csspath="/_resources/ou/editor/maincontent.css" cssmenu="/_resources/ou/editor/menu.txt" width="955" wysiwyg-class="main-content"/><div>testing stuff:</div>
<div></div>
<div></div>
<hr class="tabs-start" />
<h2>STUFF TITLE</h2>
<p>Stuff</p>
</ouc:div>
</document>

2 ответа

Два предложения

  1. Просто напишите XSLT напрямую. Необходимость динамической оценки выражений XPath является признаком того, что вы попали в стену сложности. Продолжать стучать головой не рекомендуется.
  2. Или, если вам действительно нужно изобрести свой собственный язык шаблонов на основе XML, напишите XSLT, чтобы преобразовать ваши шаблоны XML в XSLT, а затем выполните этот сгенерированный XSLT напрямую. С XSLT в качестве целевого языка вы будете иметь в своем распоряжении всю мощь (включая оценку выражений XPath, которую вы можете динамически вызывать) без необходимости полагаться на специфичные для процессора расширения.

Я бы серьезно посмотрел на второе предложение @kjhughes. Я не очень внимательно следил за описанием вашей проблемы во всех его деталях, но мне кажется, что вы разрабатываете миниатюрный язык преобразования для манипулирования вашим контентом, и я обнаружил, что когда вы обнаруживаете, что делаете это, переводите свой язык в XSLT и последующий запуск сгенерированного XSLT часто проще (и быстрее, и более переносимы), чем интерпретация языка с помощью интерпретатора, написанного на XSLT, и вызов xsl:valuate для оценки выражений пути, что в действительности и делает то, что вы делаете в данный момент.

Использование конвейерного процессора, такого как Orbeon или Calabash, может помочь в управлении общим потоком управления.

Другие вопросы по тегам