tczx3
tczx3

Reputation: 193

XPath predicate only using first node in node set for matching

I am trying to filter some incoming data through a static node set in my stylesheet. I only want referencetemplate elements whose file node contain the text of one of my file nodes. What I have is working aside from the fact that it seems to only be checking against the first file node instead of all of them. What am I missing? Or is there a better way to do this?

Input Document

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <referencetemplates>
        <referencetemplate>
            <name>Vascular Surgery Progress Note</name>
            <description>Vascular Surgery Progress Note</description>
            <file>\cernerbasiccontent\templates\standard templates\en\mun_vascular_surgery_progressnote.html</file>
            <source>cernerbasiccontent</source>
        </referencetemplate>
        <referencetemplate>
            <name>Video Visit Note</name>
            <description>Video Visit Note</description>
            <file>\cernerbasiccontent\templates\speciality templates\en\amb_video_visit.html</file>
            <source>cernerbasiccontent</source>
        </referencetemplate>
        <referencetemplate>
            <name>Well Child Office Note</name>
            <description>Well Child Office Note</description>
            <file>\cernerbasiccontent\templates\speciality templates\en\well_child_office_note.html</file>
            <source>cernerbasiccontent</source>
        </referencetemplate>
        <referencetemplate>
            <name>zzzz_IS_USE_ONLY</name>
            <description>zzzz_IS_USE_ONLY</description>
            <file>\cernerbasiccontent\templates\standard templates\en\mun_zzzz_is_use_only.html</file>
            <source>cernerbasiccontent</source>
        </referencetemplate>
    </referencetemplates>
</root>
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">

    <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" />

    <xsl:variable name="fileList">
        <file>care_management_office_visit_note.html</file>
        <file>ent_office_visit_note.html</file>
        <file>family_medicine_brief_office_visit_note.html</file>
        <file>family_medicine_office_visit_note.html</file>
        <file>gyn office visit_en.html</file>
        <file>ob_postpartum_office_note.html</file>
        <file>officeconsultnote_cardiology_en.html</file>
        <file>officeheartfailurenote_cardiology_en.html</file>
        <file>officestructuralheartnote_cardiology_en.html</file>
        <file>OfficeVisitNote_Cardiology_en.html</file>
        <file>OfficeVisitNote_Urology_en.html</file>
        <file>orthopedic_brief_office_note.html</file>
        <file>orthopedic_office_visit_note.html</file>
        <file>pediatric_office_visit_note.html</file>
        <file>physical_medicine_rehab_office_visit_note.html</file>
        <file>podiatry_office_visit_note.html</file>
        <file>pre_procedure_consultation_note.html</file>
        <file>prenatal intake office visit_en.html</file>
        <file>prenatal office visit_en.html</file>
        <file>surgical_brief_office_note.html</file>
        <file>surgical_office_visit_note.html</file>
        <file>teen_health_clinic_note_template.html</file>
        <file>well_child_office_note.html</file>
    </xsl:variable>

    <xsl:template match="/">
        <referencetemplates>
            <xsl:variable name="fileNodeSet" select="msxsl:node-set($fileList)/file" />
            <xsl:attribute name="count">
                <xsl:value-of select="count(root/referencetemplates/referencetemplate[contains(file, $fileNodeSet)])" />
            </xsl:attribute>
            <xsl:for-each select="root/referencetemplates/referencetemplate[contains(file, $fileNodeSet)]">
                <xsl:copy-of select="." />
            </xsl:for-each>
        </referencetemplates>
    </xsl:template>

</xsl:stylesheet>

EDIT: I was able to get it to work by not relying on the contains function. Thankfully, I had the ability to get the full file path into my $fileList variable and then simply did a straight equality comparison. I'm still interested in why using contains wouldn't work though...

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">

    <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" />

    <xsl:variable name="fileList">
        <file>\cernerbasiccontent\templates\speciality templates\en\care_management_office_visit_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\ent_office_visit_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\family_medicine_brief_office_visit_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\family_medicine_office_visit_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\gyn office visit_en.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\ob_postpartum_office_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\officeheartfailurenote_cardiology_en.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\officestructuralheartnote_cardiology_en.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\officevisitnote_cardiology_en.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\officevisitnote_urology_en.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\orthopedic_brief_office_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\orthopedic_office_visit_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\pediatric_office_visit_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\physical_medicine_rehab_office_visit_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\podiatry_office_visit_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\prenatal intake office visit_en.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\prenatal office visit_en.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\surgical_brief_office_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\surgical_office_visit_note.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\teen_health_clinic_note_template.html</file>
        <file>\cernerbasiccontent\templates\speciality templates\en\well_child_office_note.html</file>
    </xsl:variable>

    <xsl:template match="/">
        <referencetemplates>
            <xsl:variable name="fileNodeSet" select="msxsl:node-set($fileList)/file" />
            <xsl:attribute name="count">
                <xsl:value-of select="count(root/referencetemplates/referencetemplate[file = $fileNodeSet])" />
            </xsl:attribute>
            <xsl:for-each select="root/referencetemplates/referencetemplate[file = $fileNodeSet]">
                <xsl:copy-of select="." />
            </xsl:for-each>
        </referencetemplates>
    </xsl:template>

</xsl:stylesheet>

Upvotes: 0

Views: 197

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117165

I'm still interested in why using contains wouldn't work though...

It wouldn't work because the contains() function takes two strings as it arguments. You are calling it with a node-set as the 2nd argument - and this results (in XSLT 1.0) in converting the node-set to a string by taking the string-value of the first node in the set (in XSLT 2.0 you will get an error).

See here for two possible solutions:
https://stackoverflow.com/a/65362565/3016153

Upvotes: 1

Related Questions