Importing OAI source into Filemaker - xslt

I have a problem with importing an OAI source into Filemaker. The mapping is ok but the result is empty.
This is the source:
<OAI-PMH xmlns="http://www.openarchives.org/OAI/2.0/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dc="http://dublincore.org/documents/dcmi-namespace/" xsi:schemaLocation="http://www.openarchives.org/OAI/2.0/ http://www.openarchives.org/OAI/2.0/OAI-PMH.xsd">
<responseDate>2015-01-15T12:05:11Z</responseDate>
<request verb="ListRecords" metadataPrefix="oai_dc">
http://api.memorix-maior.nl/collectiebeheer/oai-pmh/key/SORRY_THIS_KEY_I_CANNOT_SHOW/tenant/nfm
</request>
<ListRecords>
<record>
<header>
<identifier>
e:1d59bf74-a57c-11e1-af90-bf6f69fae6b6:000a80bf-e7d6-7670-b2bd-c269b2e58878
</identifier>
etc.
And this is the xslt I made:
<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
<ERRORCODE>0</ERRORCODE>
<METADATA>
<FIELD NAME="identifier" TYPE="TEXT"/>
</METADATA>
<RESULTSET>
<xsl:for-each select="OAI-PMH/ListRecords/record">
<ROW>
<COL>
<DATA><xsl:value-of select="header/identifier"/></DATA>
</COL>
</ROW>
</xsl:for-each>
</RESULTSET>
</FMPXMLRESULT>
</xsl:template>
</xsl:stylesheet>
To make it clear I only pointed the first field in the OAI source.
I hope you can help me to fix this.
Best regards,
Boudewijn Ridder

The reason why your attempt doesn't work is that the source XML nodes are in a namespace. You must declare this namespace in your stylesheet, assign it a prefix and use that prefix when addressing the nodes:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:oai="http://www.openarchives.org/OAI/2.0/">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
<METADATA>
<FIELD NAME="identifier" TYPE="TEXT"/>
</METADATA>
<RESULTSET>
<xsl:for-each select="oai:OAI-PMH/oai:ListRecords/oai:record">
<ROW>
<COL>
<DATA><xsl:value-of select="oai:header/oai:identifier"/></DATA>
</COL>
</ROW>
</xsl:for-each>
</RESULTSET>
</FMPXMLRESULT>
</xsl:template>
</xsl:stylesheet>
Note:
If your input example is representative, you might want to use :
<xsl:value-of select="normalize-space(oai:header/oai:identifier)"/>
to trim the extraneous whitespace from the result.

Related

Issue with Accumulator in XSLT3.0

I have the below data from one data source,
<Reference>
<Worker>
<Employee_ID>1234</Employee_ID>
<Salary_Type>H</Salary_Type>
</Worker>
<Worker>
<Employee_ID>5678</Employee_ID>
<Salary_Type>H</Salary_Type>
</Worker>
</Reference>
the below data come from another data source,
<root>
<row>
<ID>1234</ID>
<ADDR>ABC</ADDR>
<PHONE>9999999998</PHONE>
<SAL>S</SAL>
</row>
<row>
<ID>5678</ID>
<ADDR>ABD</ADDR>
<PHONE>9999999999</PHONE>
<SAL>S</SAL>
</row>
</root>
I have merged the data from these data sources and have the following data,
<root>
<Reference>
<Worker>
<EmployeeID>1234</Employee_ID>
<SalaryType>H</Salary_Type>
</Worker>
<Worker>
<EmployeeID>5678</Employee_ID>
<SalaryType>H</Salary_Type>
</Worker>
</Reference>
<root>
<row>
<ID>1234</ID>
<ADDR>ABC</ADDR>
<PHONE>9999999998</PHONE>
<SAL>S</SAL>
</row>
<row>
<ID>5678</ID>
<ADDR>ABD</ADDR>
<PHONE>9999999999</PHONE>
<SAL>S</SAL>
</row>
</root>
</root>
In XSLT3.0 I m trying to replace the value of <SAL> with value of <SalaryType> with the following code, buts its not working.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="#all" version="3.0">
<xsl:mode streamable="no" on-no-match="shallow-copy" use-accumulators="#all"/>
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:accumulator name="EIDKey" as="xs:string" initial-value="''" streamable="yes">
<xsl:accumulator-rule match="/root/Reference/Worker/EmployeeID/text()" select="."/>
</xsl:accumulator>
<xsl:accumulator name="PayTypeLookup" as="map(xs:string,xs:string)" initial-value="map {}"
streamable="yes">
<xsl:accumulator-rule match="/root/Reference/Worker/SalaryType/text()"
select="map:put($value, accumulator-before('EIDKey'), string(.))"/>
</xsl:accumulator>
<xsl:template match="/">
<root>
<xsl:for-each select="root/root/row">
<row>
<xsl:apply-templates/>
</row>
</xsl:for-each>
</root>
</xsl:template>
<xsl:template match="SAL">
<xsl:variable name="PayType" select="normalize-space(.)"/>
<SAL><xsl:value-of select="accumulator-before('PayTypeLookup')($PayType)"/></SAL>
</xsl:template>
</xsl:stylesheet>
I need the final output like below, can you please help? Thanks in advance
<root>
<row>
<ID>1234</ID>
<ADDR>ABC</ADDR>
<PHONE>9999999998</PHONE>
<SAL>H</SAL>
</row>
<row>
<ID>5678</ID>
<ADDR>ABD</ADDR>
<PHONE>9999999999</PHONE>
<SAL>H</SAL>
</row>
</root>
I think you need another accumulator
<xsl:accumulator name="rowID" as="xs:string" initial-value="''" streamable="yes">
<xsl:accumulator-rule match="/root/root/row/ID/text()" select="."/>
</xsl:accumulator>
and then you can use
<xsl:template match="SAL">
<SAL><xsl:value-of select="accumulator-before('PayTypeLookup')(accumulator-before('rowID'))"/></SAL>
</xsl:template>

change element name with attribute value using XSLT

I want to change element name with attribute value
My input xml looks like below
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<ROW id="1">
<D n="ord_code">10033</D>
<D n="po_commts">Part and Service Requisition Example</D>
<D n="createddt">2021-02-11 00:00:00.0</createddt>
</ROW>
<ROW id="2">
<D n="ord_code">10018</D>
<D n="po_commts">GL Test</D>
<D n="createddt">2021-02-04 00:00:00.0</D>
</ROW>
</Envelope>
my expected result child element name replaced with attribute value
<?xml version="1.0" encoding="UTF-8"?>
<Envelope>
<ROW id="1">
<ord_code>10033</ord_code>
<po_commts>Part and Service Requisition Example</po_commts>
<createddt>2021-02-11 00:00:00.0</createddt>
</ROW>
<ROW id="2">
<ord_code>10018</ord_code>
<po_commts>GL Test</po_commts>
<createddt>2021-02-04 00:00:00.0</createddt>
</ROW>
</Envelope>
Here's how you could do it:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="D">
<xsl:element name="{#n}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
See it working here : https://xsltfiddle.liberty-development.net/gVrvcy2

Moving similar nodes to new node using XSLT

I have the following input xml:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<PQGetCareGaps>
<METHOD>GET</METHOD>
<contract>HXXXX</contract>
</PQGetCareGaps>
<FinalCareGapResults>
<Gap>
<CareGap>Colorectal Cancer Screening</CareGap>
<GapHistory>
<row>
<MEMBERID>AAAAAA000016-00</MEMBERID>
</row>
</GapHistory>
</Gap>
</FinalCareGapResults>
<FinalCareGapResults>
<Gap>
<CareGap>Adult BMI Assessment</CareGap>
</Gap>
</FinalCareGapResults>
</response>
I want to modify the above xml in such a way that all the <Gap> nodes should come under a new node called <TestResults>. The resultant xml should look like below:
<?xml version="1.0" encoding="UTF-8"?>
<response>
<PQGetCareGaps>
<METHOD>GET</METHOD>
<contract>HXXXX</contract>
</PQGetCareGaps>
<TestResults>
<Gap>
<CareGap>Colorectal Cancer Screening</CareGap>
<GapHistory>
<row>
<MEMBERID>AAAAAA000016-00</MEMBERID>
</row>
</GapHistory>
</Gap>
<Gap>
<CareGap>Adult BMI Assessment</CareGap>
</Gap>
</TestResults>
</response>
Could you please help me out?
Try this
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="1.0">
<xsl:template match="/">
<xsl:apply-templates select="response" />
</xsl:template>
<xsl:template match="response">
<response>
<xsl:copy-of select="PQGetCareGaps" />
<TestResults>
<xsl:for-each select="FinalCareGapResults/Gap">
<xsl:copy-of select="." />
</xsl:for-each>
</TestResults>
</response>
</xsl:template>
</xsl:stylesheet>

xslt calculating insurance writeoff not working

I am trying to calculate the contractual write off for medical insurance but the calculation doesn't seem to be working. For example, I need to take the value of the charge attribute on the <charge> tag and subtract the value of the amount attribute on the <adjustment> tag but only when the group and code attributes on the <adjustment> tag are: group ='CO' and code = '45' or '385'
I was able to get everything but the calculations working. I've tried looking at several answers on this forum but am obviously missing something. Any help would be appreciated.
Here is my XML (simplified):
<result check_number="05173408" ...>
<claim ... total_charge="720" total_paid="43">
<charge charge="200">
<adjustment amount="125" code="45" group="CO" />
<adjustment amount="35" code="385" group="CO" />
<adjustment amount="20" code="3" group="PR" />
</charge>
<charge charge="70">
<adjustment amount="70" code="204" group="PR" />
</charge>
<charge charge="300">
<adjustment amount="273" code="45" group="CO" />
<adjustment amount="15" code="3" group="PR" />
</charge>
<charge charge="150">
<adjustment amount="139" code="45" group="CO" />
</charge>
</claim>
</result>
Here is my xslt to date:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="xsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<!-- maps to the beginning result tag -->
<xsl:for-each select="/result/claim/charge">
<!-- amount allowed by the insurance for line item -->
<COL>
<DATA>
<xsl:apply-templates select="adjustment" mode="calcAdjTotal" >
</xsl:apply-templates>
</DATA>
</COL>
</xsl:for-each>
<!-- Template created to test Parfait's suggestion -->
<xsl:template match="adjustment" mode="calcAdjTotal" >
<xsl:variable name="condition" select="adjustment[#group='CO' and (#code='45' or #code='385')]"></xsl:variable>
<xsl:value-of select="../#charge - sum($condition/#amount)" />
</xsl:if>
</xsl:template>
</xsl:template>
</xsl:stylesheet>
Here is my output: (updated output)
<COL>
</DATA>
</COL>
<COL>
</DATA>
</COL>
<COL>
</DATA>
</COL>
<COL>
</DATA>
</COL>
Here's what I want to get:
<COL>
<DATA>
40
</DATA>
</COL>
<COL>
<DATA>
</DATA>
</COL>
<COL>
<DATA>
27
</DATA>
</COL>
<COL>
<DATA>
11
</DATA>
</COL>
The format will then be used to import data into Filemaker.
Consider wrapping your conditional equation in an <xsl:if>. Additionally, you can do so with a variable storing the conditional value to avoid repetition:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output version="1.0" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<ROOT>
<xsl:apply-templates select="*"/>
</ROOT>
</xsl:template>
<xsl:template match="charge">
<xsl:variable name="condition" select="adjustment[(#code='45' or #code='385') and #group='CO']"/>
<COL>
<DATA>
<xsl:if test="$condition">
<xsl:value-of select="#charge - sum($condition/#amount)"/>
</xsl:if>
</DATA>
</COL>
</xsl:template>
</xsl:transform>
I am guessing (!) you want something like:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/result">
<RESULT>
<xsl:for-each select="claim/charge">
<ROW>
<COL>
<DATA>
<xsl:value-of select="#charge - sum(adjustment[#group='CO' and (#code='45' or #code='385')]/#amount)" />
</DATA>
</COL>
</ROW>
</xsl:for-each>
</RESULT>
</xsl:template>
</xsl:stylesheet>
Applied to your input example, the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<RESULT>
<ROW>
<COL>
<DATA>40</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>70</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>27</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>11</DATA>
</COL>
</ROW>
</RESULT>
This assumes you want to create a record (with one field) for each charge.
Note that this is not valid FileMaker XML syntax.
-- edited in response to clarifications in comments: --
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/result">
<RESULT>
<xsl:for-each select="claim/charge[adjustment[not(#group='PR')]]">
<ROW>
<COL>
<DATA>
<xsl:value-of select="#charge - sum(adjustment[not(#group='PR')]/#amount)" />
</DATA>
</COL>
</ROW>
</xsl:for-each>
</RESULT>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<RESULT>
<ROW>
<COL>
<DATA>40</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>27</DATA>
</COL>
</ROW>
<ROW>
<COL>
<DATA>11</DATA>
</COL>
</ROW>
</RESULT>

Select value of element which is referenced by other

I have (this is an example) the following xml:
<?xml version="1.0" encoding="UTF-8"?>
<body>
<list>
<toot id="1">
<value>A</value>
</toot>
<toot id="2">
<value>B</value>
</toot>
<toot id="3">
<value>C</value>
</toot>
<toot id="4">
<value>D</value>
</toot>
</list>
<otherlist>
<foo>
<value ref="2" />
</foo>
<foo>
<value ref="3" />
</foo>
</otherlist>
</body>
And the following XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/body">
<xsl:apply-templates select="otherlist"/>
</xsl:template>
<xsl:template match="otherlist">
<xsl:for-each select="foo">
<result>
<value><xsl:value-of select="/body/list/toot[#id=value/#ref]/value" /></value><!-- This is the important -->
<ref><xsl:value-of select="value/#ref" /></ref>
</result>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
And this is the result when it make/transform the xml:
<?xml version="1.0" encoding="UTF-8"?>
<result>
<value/>
<ref>2</ref>
</result>
<result>
<value/>
<ref>3</ref>
</result>
And the problem is that is empty. What I wanna get is:
<?xml version="1.0" encoding="UTF-8"?>
<result>
<value>B</value>
<ref>2</ref>
</result>
<result>
<value>C</value>
<ref>3</ref>
</result>
I think the problem is the XPath /body/list/toot[#id=value/#ref]/value specifically the condition [#id=value/#ref]. Is not correct it? How to use a value of other element witch is reference by the current one?
Yes the problem is in XPath where the context is changing so you are actually looking for toot element which has #id attribute and value child with #ref attribute (which is actually child of foo) and these two are equal.
You can employ current() function to make it working
<xsl:value-of select="/body/list/toot[#id=current()/value/#ref]/value"/>
Or you can store value of #ref into a variable and use this variable in predicate
<xsl:variable name="tmpRef" select="value/#ref" />
<xsl:value-of select="/body/list/toot[#id=$tmpRef]/value"/>