xpath, чтобы увидеть, существует ли «текущий узел» во внешнем файле атрибута набора узлов - PullRequest
0 голосов
/ 27 ноября 2018

Фон У меня есть проверка схемы и перевод xslt в pdf.

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

<xsl:template match="//medicalFieldcode" priority="1000" mode="M4">
    <svrl:fired-rule xmlns:svrl="http://purl.oclc.org/dsdl/svrl" context="//medicalFieldcode"/>
    <xsl:variable name="MVOcodes" select="document('verksamhetskodlista.xml')"/>

    <!--ASSERT -->
    <xsl:choose>

        <xsl:when test="boolean($MVOcodes/module/document-merge/g-funcs/g[contains(@name,.)])"/>

        <xsl:otherwise>
            <svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
                            test="boolean($MVOcodes/module/document-merge/g-funcs/g[contains(@name,.)])">
                <xsl:attribute name="id">R43</xsl:attribute>
                <xsl:attribute name="location">
                    <xsl:apply-templates select="." mode="schematron-select-full-path"/>
                </xsl:attribute>
                <svrl:text>MedicalFieldCode must be in the valid list of codes.</svrl:text>
            </svrl:failed-assert>
        </xsl:otherwise>
    </xsl:choose>
    <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M4"/>
</xsl:template>

Внешний файл (verksamhetskodlista.xml) имеет следующую структуру:

<module xmlns:mmx="http://funx" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:svg="http://www.w3.org/2000/svg" xmlns:fnc="http://funx/fnc" xmlns:att="http://funx/att" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<document-merge>
    <g-funcs>
        <g name="003">value1</g>
        <g name="009">another value</g>
        <g name="011">yet another value</g>
        <!-- ... -->
    </g-funcs>
</document-merge>

Извлечьиз образца xml:

<ProcessClaimSpecification xmlns="urn:riv:financial:billing:claim:ProcessClaimSpecificationResponder:1">
<s01:claimSpecification xmlns="urn:riv:financial:billing:claim:1" xmlns:s01="urn:riv:financial:billing:claim:ProcessClaimSpecificationResponder:1">
    <healthCareServicesSpecificationLine>
        <healthcarePerformed>
            <!-- a bunch of content --> 
            <activity>
                <medicalFieldCode>000</medicalFieldCode>
            </activity>
        </healthcarePerformed>
    </healthCareServicesSpecificationLine>
</s01:claimSpecification>

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

Проблема в том, что он всегда отображается как true, даже если используется 000, которого нет в списке кодов.Я пробовал много разных реструктурированных разновидностей содержимого xpath, но он не работает удовлетворительно.Я не уверен, что пришел с правильного угла здесьЯ использую xslt 2.0, поэтому переменная должна содержать набор узлов.

Помимо прочего, я пробовал эти выражения xpath

boolean($MVOcodes/module/document-merge/g-funcs/g[contains(@name,.)])
contains($MVOcodes/module/document-merge/g-funcs/g/@name, .)

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

Ответы [ 2 ]

0 голосов
/ 29 ноября 2018

Как указывает Тони Грэм, Xpath, вероятно, можно упростить, используя вместо этого существующее.И тип: о это тоже то, что я упустил из виду.Отсутствующее пространство имен в контексте xpath также верно.Спасибо за указание на эти вещи!

Однако я обнаружил, что уже существует правило для того же узла xml выше в файле схемы.Я закончил тем, что добавил к этому еще один <assert>, и он сработал (вместе с некоторыми другими изменениями).

Вот как это выглядит сейчас в файле schematron:

<rule context="//urn2:activity/urn2:medicalFieldCode" flag="fatal">
    <assert id="R33" test="((count(../../urn2:diagnosis) = 0) and (count(../../urn2:treatment) = 0)) or not(starts-with(., '9'))">Diagnoser och åtgärder får ej förekomma när medicalFieldCode börjar med 9. Underlags-id: <value-of select="//urn1:claimSpecification/urn2:id"/></assert>
    <assert id="R43" test="boolean(document('verksamhetskodlista.xml')/module/document-merge/g-funcs/g[contains(@name, current()/text())])" flag="fatal">MedicalFieldCode must be in the valid list of codes.</assert>
</rule>

Что делаетэто скомпилированный XSLT:

<xsl:template match="//urn2:activity/urn2:medicalFieldCode" priority="1007" mode="M3">
  <svrl:fired-rule xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
                   context="//urn2:activity/urn2:medicalFieldCode"/>

        <!--ASSERT -->
<xsl:choose>
     <xsl:when test="((count(../../urn2:diagnosis) = 0) and (count(../../urn2:treatment) = 0)) or not(starts-with(., '9'))"/>
     <xsl:otherwise>
        <svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
                            test="((count(../../urn2:diagnosis) = 0) and (count(../../urn2:treatment) = 0)) or not(starts-with(., '9'))">
           <xsl:attribute name="id">R33</xsl:attribute>
           <xsl:attribute name="location">
              <xsl:apply-templates select="." mode="schematron-select-full-path"/>
           </xsl:attribute>
           <svrl:text>Diagnoser och åtgärder får ej förekomma när medicalFieldCode börjar med 9. Underlags-id: <xsl:text/>
              <xsl:value-of select="//urn1:claimSpecification/urn2:id"/>
              <xsl:text/>
           </svrl:text>
        </svrl:failed-assert>
     </xsl:otherwise>
  </xsl:choose>

        <!--ASSERT -->
<xsl:choose>
     <xsl:when test="boolean(document('verksamhetskodlista.xml')/module/document-merge/g-funcs/g[contains(@name, current()/text())])"/>
     <xsl:otherwise>
        <svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
                            test="boolean(document('verksamhetskodlista.xml')/module/document-merge/g-funcs/g[contains(@name, current()/text())])">
           <xsl:attribute name="id">R43</xsl:attribute>
           <xsl:attribute name="flag">fatal</xsl:attribute>
           <xsl:attribute name="location">
              <xsl:apply-templates select="." mode="schematron-select-full-path"/>
           </xsl:attribute>
           <svrl:text>MedicalFieldCode must be in the valid list of codes.</svrl:text>
        </svrl:failed-assert>
     </xsl:otherwise>
  </xsl:choose>
  <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M3"/>
</xsl:template>

Согласно моим тестовым файлам, это работает как задумано.

Файл предназначен для сбоя:

Result AnalyzeSchematronResult: MedicalFieldCode must be in the valid list of codes.

Файл предназначен для успеха:

Passed OK Schematronvalidate

Еще раз спасибо за ваши полезные дополнения и полезные комментарии.

0 голосов
/ 28 ноября 2018

Поскольку это вопрос Schematron, возможно, было бы яснее, если бы вы разместили Schematron, а не XSLT, который генерируется из Schematron.На самом деле, я работал с вашим XSLT, и я оставлю вам возможность изменить ваш Schematron для работы таким же образом.

Во-первых, ваш текущий XSLT соответствует medicalFieldcode, а не medicalFieldCode.Обратите внимание на c против C.

Во-вторых, вам, вероятно, нужно пространство имен в XPath для вашего элемента контекста.В приведенном ниже примере я использую префикс claim для URI пространства имен urn:riv:financial:billing:claim:1.

В-третьих, . в XPath означает текущий контекст (см. https://www.w3.org/TR/2010/REC-xpath20-20101214/#doc-xpath-ContextItemExpr). Поэтому, когда вы используете. в g[contains(@name,.)], контекст является элементом <g>, поэтому вы сравниваете строковое значение элемента со значением одного из его атрибутов. Обычная вещь, которую нужно сделать, когда вы пытаетесь использовать что-то из оригиналаконтекст внутри предиката - объявлять и использовать переменную для значения, которое вы хотите использовать. В Schematron вы будете использовать элемент <let>.

В-четвертых, exists() - это полезный XPath 2.0 (и позже) способ узнать, соответствует ли XPath чему-либо. То есть, если XPath не оценивает пустую последовательность (см. https://www.w3.org/TR/xquery-operators/#func-exists).

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

Полученный модифицированный XSLT, который я оставлю вам, чтобы вернуться в Schematron, выглядит так:

<xsl:template match="//claim:medicalFieldCode" priority="1000">
    <svrl:fired-rule xmlns:svrl="http://purl.oclc.org/dsdl/svrl" context="//medicalFieldcode"/>
    <xsl:variable name="MVOcodes" select="document('verksamhetskodlista.xml')"/>
    <xsl:variable name="code" select="." />

    <!--ASSERT -->
    <xsl:choose>

        <xsl:when test="exists($MVOcodes/module/document-merge/g-funcs/g[@name eq $code])"/>

        <xsl:otherwise>
            <svrl:failed-assert xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
                            test="exists($MVOcodes/module/document-merge/g-funcs/g[contains(@name,.)])">
                <xsl:attribute name="id">R43</xsl:attribute>
                <xsl:attribute name="location">
                    <xsl:apply-templates select="." mode="schematron-select-full-path"/>
                </xsl:attribute>
                <svrl:text>MedicalFieldCode must be in the valid list of codes.</svrl:text>
            </svrl:failed-assert>
        </xsl:otherwise>
    </xsl:choose>
    <xsl:apply-templates select="*|comment()|processing-instruction()" mode="M4"/>
</xsl:template>
...