#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, если оно найдено / не найдено.