Xslt создание карты исключений и итерация с функцией

#xml #xslt #xpath

#xml #xslt #xpath

Вопрос:

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

Это пример ввода, который я пытаюсь обработать. В базе данных имеется большое количество таких записей. Моя цель — создать простую редактируемую карту в верхней части таблицы стилей, которую пользователь может редактировать, чтобы добавить правило для исключения записи. Так, например, они могли бы сделать исключение на основе order_id или product_id . Карта будет содержать путь к узлу в качестве ключа и значение узла, которое будет соответствовать правилу исключения.

 <row>
    <row_number>14122</row_number>
    <order_id>14590</order_id>
    <order_item_seq_id></order_item_seq_id>
    <status_id></status_id>
    <customer_id>14590</customer_id>
    <company_name>Customer 1</company_name>
    <main_contact_name>Example Customer</main_contact_name>
    <email_address>example@company.org</email_address>
    <country_code xsi:nil="true" />
    <local_number></local_number>
    <address1></address1>
    <address2></address2>
    <city></city>
    <state_province_geo_id></state_province_geo_id>
    <postal_code></postal_code>
    <site_id></site_id>
    <company_location_name></company_location_name>
    <location_contact_name></location_contact_name>
    <site_main_number></site_main_number>
    <site_email_address></site_email_address>
    <site_country_code></site_country_code>
    <site_local_number></site_local_number>
    <site_address1></site_address1>
    <site_address2></site_address2>
    <site_city></site_city>
    <site_state_province_geo_id></site_state_province_geo_id>
    <site_postal_code></site_postal_code>
    <type_id>CUSTOMER</type_id>
    <product_id>PROD_1</product_id>
    <service_profile_item_seq_id></service_profile_item_seq_id>
    <quantity>0</quantity>
    <unit_price>0.00</unit_price>
    <seller_sales_code>Example</seller_sales_code>
    <entry_sales_code></entry_sales_code>
</row>
  

Вот моя карта, которую я хочу использовать для исключений. Идея здесь в том, что ключом является xpath со значением.

 <xsl:variable name="exclusions">
    <exclusion key="customer_id">49510</exclusion>
    <exclusion key="customer_id">49673</exclusion>
    <exclusion key="production_id">PROD_1</exclusion>
</xsl:variable>
  

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

 <xsl:function name="isExclusion" as="xs:boolean">
    <xsl:param name="toCheck" />
    <xsl:for-each select="exclusions/exclusion">
        <xsl:choose>
            <xsl:when test="toCheck/@key = '.'">
                <xsl:value-of select="true()" />
            </xsl:when>
        </xsl:choose>
    </xsl:for-each>
</xsl:function>
  

Это может быть неправильным решением, но любые советы будут с благодарностью. Я действительно хотел бы даже создать функцию, которая обрезает входные данные для исключений перед обработкой. В противном случае мне придется вызывать isExclusion несколько раз в моем коде. Я довольно долго искал пример такого решения, но не смог найти хороший пример, который поможет мне решить эту проблему.

Заранее спасибо.

Комментарии:

1. Пожалуйста, отредактируйте и убедитесь, что вы используете, например $toCheck , если хотите ссылаться на параметр, который вы объявили как <xsl:param name="toCheck" /> . Также неясно select="exclusions/entry" , предназначено ли для ссылки на переменную exclusions , в этом случае вам понадобится select="$exclusions/entry" . Как правило, в функции, если вы хотите вернуть логическое значение на основе условия, я бы просто использовал, например <xsl:sequence select="$toCheck/@key = '.'"/> . Основное внимание уделяется использованию xsl:sequence и логическому выражению в select атрибуте.

2. Мартин, большое спасибо за вашу помощь. Я изменил карту, чтобы использовать исключение из записи, но не изменил шаблон. Спасибо, что поняли это.

3. Мартин, я обновил вопрос ответом, который я тестирую. Имеет ли это смысл и видите ли вы какие-либо проблемы?

4. Я предлагаю сделать тело функции чем-то вроде <xsl:sequence select="$exclusions/exclusion/@key = $toCheck/@key"/> . Это конкретное выражение, которое я написал, вероятно, не то, что вы хотите, поскольку пока я не уверен в проверке, которую вы хотите сделать.

5. Я обновил вопрос фактическим вводом, который будет передан в таблицу стилей. Я думаю, что моя проблема в том, что я не могу понять, как выполнить простой цикл for, а затем вернуть true, если узел найден в списке исключений. Возможно, невозможно решить проблему так, как я собираюсь это сделать.

Ответ №1:

Если вы хотите вернуть логическое значение, просто используйте xsl:sequence с select атрибутом, который является логическим выражением.

Не используйте xsl:value-of , как оба <xsl:value-of select="true()"/> , или <xsl:value-of select="false()"/> создайте текстовый узел с непустым строковым значением, которое вы as="xs:boolean" преобразуете в логическое значение true .

Комментарии:

1. Мартин, я думаю, ты даешь мне ответ, который мне нужен, но я не понимаю, как его реализовать. Я попытался создать простой узел <xsl:text> и выполнить для него true, но я получаю сообщение об ошибке «XPTY0004: пустая последовательность не разрешена в результате функции». Это имеет смысл, потому что я не всегда возвращаю значение. Извините, но я не понимаю, как последовательность поможет мне в этом случае. Я прочитал о последовательности здесь saxonica.com/documentation/xsl-elements/sequence.html но я не уверен, как это поможет мне вернуть значение true или false, если оно найдено / не найдено.