XPath Axes child - xpath

I have a problem with XPath Axes child::* .
this expression $x[1]/child::* correctly selects all child nodes
buy this $x[1]/child::y it doesn't select anything, but it should select nodes with that name
this is how the variable x is valued
<xsl:param name="x" select="/a/b" />
this is the xml:
<a>
<b>
<c>
</c>
<d>
</d>
<e>
</e>
<f>
</f>
<g>
</g>
.
.
.
.
<y>
</y>
</b>
<b>
<c>
</c>
<d>
</d>
<e>
</e>
<f>
</f>
<g>
</g>
.
.
.
.
<y>
</y>
</b>
</a>
please help me.
EDIT
this is the really xml (with test value):
<?xml version="1.0" encoding="UTF-8"?>
<!--Sample XML file generated by XMLSpy v2020 rel. 2 sp1 (x64) (http://www.altova.com)-->
<CRR xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:n1="urn:crif-cribiscom-Report-Company:2012-04-01" xmlns:n2="http://www.altova.com/samplexml/other-namespace" ASYNCID="String" LUD="1957-08-13" xsi:schemaLocation="urn:crif-cribiscom-Report-Company:2012-04-01 Crif.CribisCom.Report.Company.xsd">
<BSs>
<BS4D N="2">
<C>
<BSD>
<IBS>
<BH CD="1957-08-13" SC="String" SCD="String" CCD="String" CC="String" ACD="String" AC="String" SCC="String" SCCD="String" FBR="String" VN="String" BS="String" FRF="text"/>
<BI>
<IC>
<SA>
<A CI="St ring" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Abis CI="String" V="0" D="String"/>
<Ater CI="String" V="0" D="String"/>
<B CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<C CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<D CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Dbis CI="String" V="0" D="String"/>
<E CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
</SA>
<SP>
<A CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<B CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<C CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<D CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Dbis CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Dter CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<E CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Ebis CI="String" V="0" D="String"/>
<F CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<G CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Gbis CI="String" V="0" D="String"/>
</SP>
</IC>
</BI>
</IBS>
</BSD>
<BSD>
<IBS>
<BH CD="1957-08-13" SC="String" SCD="String" CCD="String" CC="String" ACD="String" AC="String" SCC="String" SCCD="String" FBR="String" VN="String" BS="String" FRF="text"/>
<BI>
<IC>
<SA>
<A CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Abis CI="String" V="0" D="String"/>
<Ater CI="String" V="0" D="String"/>
<B CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<C CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<D CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Dbis CI="String" V="0" D="String"/>
<E CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
</SA>
<SP>
<A CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<B CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<C CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<D CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Dbis CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Dter CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<E CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Ebis CI="String" V="0" D="String"/>
<F CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<G CI="String" V="0" D="String" SD="0" SCI="String" CCI="String"/>
<Gbis CI="String" V="0" D="String"/>
</SP>
</IC>
</BI>
</IBS>
</BSD>
</C>
</BS4D>
</BSs>
</CRR>
I want to select the node ../BI/IC/SA/A or ../BI/IC/SA/Abis or ../BI/IC/SA/Ater ecc... in parallel with ancestor node C/BSD.
I hope it's more understandable.

Related

XSLT - how can I filter data source by data from external XML?

I have the following XML data structure:
<root>
<info>
<creationDate>2015-03-11 11:45:49</creationDate>
</info>
<promotions>
<promotion>
<header>
<id>1</id>
<name>Name 1</name>
</header>
<positions>
<position>
<id>1</id>
<name>Some position name 1</name>
</position>
<position>
<id>2</id>
<name>Some position name 2</name>
</position>
</position>
</positions>
</promotion>
<promotion>
<header>
<id>2</id>
<name>Name 2</name>
</header>
<positions>
<position>
<id>3</id>
<name>Some position name 3</name>
</position>
</positions>
</promotion>
</promotions>
</root>
Which is used as primary data source for my template like this:
<xsl:template match="root">
...
I need to filter the above by "filter.xml" file, containing promotion Id's to filter out, and it needs to work on IE7 . Is something like this possible?
For starters I tried to find a way to add filter in xsl:apply-templates select statement, so that only promotion with Id=2 will be processed by template but failed - is it possible to write Xpath that will say:
"Give me everything from root node but promotions only with Id = 2" ?
Thanks.
EDIT1:
Sorry about the namespace - it shouldn't be there in the first place. As for the filter.xml - it is not clearly defined yet - for now, I'm using the following:
<usedUpPromotions>
<header>
<promotionId>
1
</promotionId>
</header>
<header>
<promotionId>
2
</promotionId>
</header>
<header>
<promotionId>
3
</promotionId>
</header>
</usedUpPromotions>
I think of using something like:
<xsl:apply-templates select="root[hereIsMyWhereId != (document('Load externalXmlHere')/select/IdtoFilterOut)"/>
But I can't seem to find a way to filter out data that way...
EDIT2:
I'll try to explain using code as example - let's assume for a moment that we have the following:
XmlData initialXmlData; <- this is our XML data before filtering
XmlData filter; -< this contains the filter.xml data
Html GenerateHtmlFromTemplate(XmlData initialXmlData) - this is my Xslt template
{
...some precessing here
}
I would like to modify my template to achieve the following:
Html GenerateHtmlFromTemplate(XmlData initialXmlData, XmlData filter)
{
XmlData filteredData = data.FilterBy(filter);
...same processing here as above, but use 'filteredData', instead of 'initialXmlData'
}
I hope it's more clear now :) - the main problem, it would seem is that the Id element, I want to filter by, is inside array variable, so I cannot simply use:
in my primary template - instead I bypassed the problem, by filtering on for-each loop later on but I would still like to know if it is possible to simply tell the template "from now on use filtered data, instead of original".
Edit3:
#michael.hor257k - to answer your question, I have modified templates you provided:
Template.xml:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="#"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ksx="http://www.test.com/test" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<xsl:output encoding="utf-8" indent="no" method="html"/>
<root xmlns="http://www.test.com/test">
<info>
<creationDate>2015-03-11 11:45:49</creationDate>
</info>
<promotions>
<promotion>
<header>
<id atr="tre">1</id>
<name>Promotion 1</name>
</header>
<positions>
<position>
<id>1</id>
<name>Position 1a</name>
</position>
<position>
<id>2</id>
<name>Position 1b</name>
</position>
</positions>
</promotion>
<promotion>
<header>
<id>2</id>
<name>Promotion 2</name>
</header>
<positions>
<position>
<id>3</id>
<name>Position 2a</name>
</position>
</positions>
</promotion>
</promotions>
</root>
<xsl:param name="new-path" select="'new.xml'"/>
<xsl:variable name="new-promotions" select="document($new-path)/newPromotions/promotion" />
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="ksx:root">
<xsl:copy>
<xsl:apply-templates select="ksx:promotions/ksx:promotion[not(ksx:header/ksx:id=$new-promotions/header/id)]"/>
<xsl:apply-templates select="$new-promotions"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
new.xml:
<?xml version="1.0" encoding="utf-8"?>
<newPromotions>
<promotion>
<header>
<id>2</id>
<name>New Promotion 2</name>
</header>
<positions>
<position>
<id>4</id>
<name>New Position 2A</name>
</position>
</positions>
</promotion>
<promotion>
<header>
<id>3</id>
<name>New Promotion 3</name>
</header>
<positions>
<position>
<id>5</id>
<name>New Position 3A</name>
</position>
</positions>
</promotion>
</newPromotions>
If you save those, and open template.xml in Chrome it will work nicely - what I wanted however was to filter out data outside template node:
<xsl:template match="ksx:root">
So, I tried this:
<xsl:template match="ksx:root[ksx:promotion/ksx:header/ksx:id=1]">
And I expected to get all data from root but with promotions filtered to those with Id = 1 - but it gave all data and no errors, now I noticed that this:
<xsl:template match="ksx:root[ksx:promotions/ksx:promotion/ksx:header/ksx:id=$new-promotions/header/id]">
causes an error "Variables cannot be used within this expression" - so I guess, what I want to do is probably impossible from outside the template node...?
Sorry for the confusion - I hope now it is more clear. I simply wanted to treat template node as a method and "pass" filtered data to it, instead of filtering the data inside of it.
Edit4:
In my specific case, I have large "root" dataset of promotions, and small, external XML file that contains promotion Id's to hide during processing. So in my case filtering would mean: "Take everything from root element, but filter promotions so only those which Ids are NOT in the external file, will be processed". So if I have:
<root xmlns="http://www.test.com/test">
<info>
<creationDate>2015-03-11 11:45:49</creationDate>
</info>
<someData1>Some data 1</someData1>
<someData2>Some data 2</someData2>
<someData3>Some data 3</someData3>
<promotions>
<promotion>
<header>
<id>1</id>
<name>Promotion 1</name>
</header>
<positions>
<position>
<id>1</id>
<name>Position 1a</name>
</position>
<position>
<id>2</id>
<name>Position 1b</name>
</position>
</positions>
</promotion>
<promotion>
<header>
<id>2</id>
<name>Promotion 2</name>
</header>
<positions>
<position>
<id>3</id>
<name>Position 2a</name>
</position>
</positions>
</promotion>
<promotion>
<header>
<id>3</id>
<name>Promotion 3</name>
</header>
<positions>
<position>
<id>4</id>
<name>Position 3a</name>
</position>
</positions>
</promotion>
</promotions>
</root>
And filter by:
<?xml version="1.0" encoding="UTF-8"?>
<usedUpPromotions>
<id>1</id>
<id>2</id>
</usedUpPromotions>
Then I would expect to get:
<root xmlns="http://www.test.com/test">
<info>
<creationDate>2015-03-11 11:45:49</creationDate>
</info>
<someData1>Some data 1</someData1>
<someData2>Some data 2</someData2>
<someData3>Some data 3</someData3>
<promotions>
<promotion>
<header>
<id>3</id>
<name>Promotion 3</name>
</header>
<positions>
<position>
<id>4</id>
<name>Position 3a</name>
</position>
</positions>
</promotion>
</promotions>
</root>
To process only promotions with Id=2, you can use (from the context of root):
<xsl:apply-templates select="promotions/promotion[header/id='2']"/>
Added:
Here's an example showing how you can "merge" your input XML with an overriding XML document. Given:
XML
<root>
<info>
<creationDate>2015-03-11 11:45:49</creationDate>
</info>
<promotions>
<promotion>
<header>
<id>1</id>
<name>Promotion 1</name>
</header>
<positions>
<position>
<id>1</id>
<name>Position 1a</name>
</position>
<position>
<id>2</id>
<name>Position 1b</name>
</position>
</positions>
</promotion>
<promotion>
<header>
<id>2</id>
<name>Promotion 2</name>
</header>
<positions>
<position>
<id>3</id>
<name>Position 2a</name>
</position>
</positions>
</promotion>
</promotions>
</root>
new.xml
<newPromotions>
<promotion>
<header>
<id>2</id>
<name>New Promotion 2</name>
</header>
<positions>
<position>
<id>4</id>
<name>New Position 2A</name>
</position>
</positions>
</promotion>
<promotion>
<header>
<id>3</id>
<name>New Promotion 3</name>
</header>
<positions>
<position>
<id>5</id>
<name>New Position 3A</name>
</position>
</positions>
</promotion>
</newPromotions>
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:strip-space elements="*"/>
<xsl:param name="new-path" select="'path/to/new.xml'"/>
<xsl:variable name="new-promotions" select="document($new-path)/newPromotions/promotion" />
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="promotions">
<xsl:copy>
<xsl:apply-templates select="promotion[not(header/id=$new-promotions/header/id)]"/>
<xsl:apply-templates select="$new-promotions"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<root>
<info>
<creationDate>2015-03-11 11:45:49</creationDate>
</info>
<promotions>
<promotion>
<header>
<id>1</id>
<name>Promotion 1</name>
</header>
<positions>
<position>
<id>1</id>
<name>Position 1a</name>
</position>
<position>
<id>2</id>
<name>Position 1b</name>
</position>
</positions>
</promotion>
<promotion>
<header>
<id>2</id>
<name>New Promotion 2</name>
</header>
<positions>
<position>
<id>4</id>
<name>New Position 2A</name>
</position>
</positions>
</promotion>
<promotion>
<header>
<id>3</id>
<name>New Promotion 3</name>
</header>
<positions>
<position>
<id>5</id>
<name>New Position 3A</name>
</position>
</positions>
</promotion>
</promotions>
</root>
In response to your edit #4:
So in my case filtering would mean: "Take everything from root
element, but filter promotions so only those which Ids are NOT in the
external file, will be processed".
My answer above does two things:
It copies everything from the input XML document except promotions whose IDs are in the external file;
It adds all the promotions listed in the external file.
If you only want to do #1 but not #2, then change this:
<xsl:template match="promotions">
<xsl:copy>
<xsl:apply-templates select="promotion[not(header/id=$new-promotions/header/id)]"/>
<xsl:apply-templates select="$new-promotions"/>
</xsl:copy>
</xsl:template>
to:
<xsl:template match="promotions">
<xsl:copy>
<xsl:apply-templates select="promotion[not(header/id=$new-promotions/header/id)]"/>
</xsl:copy>
</xsl:template>
In the given example, the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<info>
<creationDate>2015-03-11 11:45:49</creationDate>
</info>
<promotions>
<promotion>
<header>
<id>1</id>
<name>Promotion 1</name>
</header>
<positions>
<position>
<id>1</id>
<name>Position 1a</name>
</position>
<position>
<id>2</id>
<name>Position 1b</name>
</position>
</positions>
</promotion>
</promotions>
</root>

Xquery for following-siblings, but contiguous?

I need an XPath query that originates at node 'a' to return some number of contiguously-following 'b' nodes and some number of contiguously-following 'c' nodes. So in this snippet-
<a />
<b />
<b />
<c />
<d />
<e />
<a />
<b />
<b />
<b />
<b />
<c />
it would be-
<b />
<b />
<c />
If I ran it against the first 'a' node and
<b />
<b />
<b />
<b />
<c />
If I ran it against the 2nd.
Ordering matters and I can't find a solution that does not involve unioning separate expressions.
The best bet for this is probably a recursive function something like
declare function local:successors($n as node()) as node()* {
if ($n/following-sibling::*[1][self::b|self::c])
then ($n, local-successors($n/following-sibling::*[1])
else $n
};
local:successors($a)
That's assuming you want XQuery as in your title, not XPath as in the body of your question.

FHIR - Repeated patient resource on a single xml message

We are querying a web service to retrieve a list of patients.
Is there a way to encapsulate several tags in a root element that matches the FHIR standard ?
Or is FHIR dedicated to manage patient one by one ?
There is a way to retrieve a list of patients. Here's examples:
http://fhir.healthintersections.com.au/open/Patient?_id=1,2,example (DSTU 1)
http://fhir-dev.healthintersections.com.au/open/Patient?_id=1,2,example (Candidate DSTU 2)
If you just use those URLs directly, you'll get an HTML view of the underlying format. Use a REST explorer (e.g. Postman) to see the underlying XML, which, for the DSTU 1 case, looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Search results for resource type Patient</title>
<id>urn:uuid:fac88057-33e9-4401-86da-c86027d36b</id>
<link href="http://fhir.healthintersections.com.au/open/" rel="fhir-base" />
<link href="http://fhir.healthintersections.com.au/open/Patient/_search?_format=text/xml+fhir&search-id=ac47863c-3d02-4ac8-9fdd-fcb2467f60&&_id=1%2C2%2Cexample&search-sort=_id" rel="self" />
<updated>2015-01-08T20:27:45Z</updated>
<totalResults xmlns="http://a9.com/-/spec/opensearch/1.1/">3</totalResults>
<entry>
<title>Patient "1" Version "22"</title>
<id>http://fhir.healthintersections.com.au/open/Patient/1</id>
<link href="http://fhir.healthintersections.com.au/open/Patient/1/_history/22" rel="self" />
<updated>2014-12-23T17:34:02Z</updated>
<author>
<name>Anonymous (155.230.118.94)</name>
</author>
<published>2015-01-08T20:27:45Z</published>
<content type="text/xml">
<Patient xmlns="http://hl7.org/fhir">
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">Everywoman, Eve. SSN:
444222222</div>
</text>
<identifier>
<label value="SSN"/>
<system value="http://hl7.org/fhir/sid/us-ssn"/>
<value value="444222222"/>
</identifier>
<name>
<use value="official"/>
<family value="Everywoman"/>
<given value="Susan"/>
</name>
<telecom>
<system value="phone"/>
<value value="555-555-2003"/>
<use value="work"/>
</telecom>
<gender>
<coding>
<system value="http://hl7.org/fhir/v3/AdministrativeGender"/>
<code value="M"/>
</coding>
</gender>
<birthDate value="2002-09-09"/>
<address>
<use value="home"/>
<line value="2222 Home Street"/>
</address>
<managingOrganization>
<reference value="Organization/hl7"/>
</managingOrganization>
<active value="true"/>
</Patient>
</content>
<summary type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">Everywoman, Eve. SSN:
444222222</div>
</summary>
</entry>
<entry>
<title>Patient "2" Version "2"</title>
<id>http://fhir.healthintersections.com.au/open/Patient/2</id>
<link href="http://fhir.healthintersections.com.au/open/Patient/2/_history/2" rel="self" />
<updated>2014-11-07T06:17:07Z</updated>
<author>
<name>Anonymous (72.130.166.78)</name>
</author>
<published>2015-01-08T20:27:45Z</published>
<content type="text/xml">
<Patient xmlns="http://hl7.org/fhir">
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">Everyman, Adam. SSN:
444333333</div>
</text>
<identifier>
<label value="SSN"/>
<system value="http://hl7.org/fhir/sid/us-ssn"/>
<value value="444333333"/>
</identifier>
<name>
<use value="official"/>
<family value="Everyman"/>
<given value="Adam"/>
</name>
<telecom>
<system value="phone"/>
<value value="555-555-2014"/>
<use value="work"/>
</telecom>
<gender>
<coding>
<system value="http://hl7.org/fhir/v3/AdministrativeGender"/>
<code value="M"/>
</coding>
</gender>
<address>
<use value="home"/>
<line value="2222 Home Street"/>
</address>
<managingOrganization>
<reference value="Organization/hl7"/>
</managingOrganization>
<active value="true"/>
</Patient>
</content>
<summary type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">Everyman, Adam. SSN:
444333333</div>
</summary>
</entry>
<entry>
<title>Patient "example" Version "25"</title>
<id>http://fhir.healthintersections.com.au/open/Patient/example</id>
<link href="http://fhir.healthintersections.com.au/open/Patient/example/_history/25" rel="self" />
<updated>2014-12-02T06:23:30Z</updated>
<author>
<name>Anonymous (1.22.102.13)</name>
</author>
<published>2015-01-08T20:27:45Z</published>
<content type="text/xml">
<Patient xmlns="http://hl7.org/fhir">
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<p>
<b>Generated Narrative</b>
</p><p>
<b>name</b>: </p>
<ul>
<li>Peter Chalmers </li>
<li>Peter Chalmers </li>
</ul><p>
<b>telecom</b>: </p>
<ul>
<li>ph: (03) 5555 6473</li>
<li>ph: -unknown-</li>
<li>peter.chalmers#healthintersections.com</li>
<li>ph: (03) 5555 6473</li>
<li>ph: -unknown-</li>
<li>peter.chalmers#healthintersections.com</li>
</ul><p>
<b>gender</b>: Male <span style="background: LightGoldenRodYellow ">(Details : { code "M" := "", given as "Male"})</span>
</p><p>
<b>birthDate</b>: 1974-11-25T00:11:00+05:30</p><p>
<b>deceased</b>: -1</p><p>
<b>address</b>: </p>
<ul>
<li>534 Erewhon St PleasantVille Alabama 3999 </li>
<li>534 Erewhon St PleasantVille Alabama 3999 </li>
</ul><p>
<b>maritalStatus</b>: Single <span style="background: LightGoldenRodYellow ">(Details )</span>
</p><p>
<b>multipleBirth</b>: 0</p><p>
<b>communication</b>: </p>
<ul>
<li>Spanish <span style="background: LightGoldenRodYellow ">(Details )</span>
</li>
<li>English <span style="background: LightGoldenRodYellow ">(Details )</span>
</li>
<li>Spanish <span style="background: LightGoldenRodYellow ">(Details )</span>
</li>
<li>English <span style="background: LightGoldenRodYellow ">(Details )</span>
</li>
</ul><p>
<b>careProvider</b>: </p>
<ul>
<li>
Practitioner/131
</li>
<li>
Practitioner/132
</li>
<li>
Practitioner/133
</li>
<li>
Practitioner/134
</li>
<li>
Practitioner/143
</li>
</ul>
</div>
</text>
<name>
<family value="Chalmers"/>
<given value="Peter"/>
</name>
<name>
<family value="Chalmers"/>
<given value="Peter"/>
</name>
<telecom>
<system value="phone"/>
<value value="(03) 5555 6473"/>
</telecom>
<telecom>
<system value="phone"/>
</telecom>
<telecom>
<system value="email"/>
<value value="peter.chalmers#healthintersections.com"/>
</telecom>
<telecom>
<system value="phone"/>
<value value="(03) 5555 6473"/>
</telecom>
<telecom>
<system value="phone"/>
</telecom>
<telecom>
<system value="email"/>
<value value="peter.chalmers#healthintersections.com"/>
</telecom>
<gender>
<coding>
<code value="M"/>
<display value="Male"/>
</coding>
<text value="Male"/>
</gender>
<birthDate value="1974-11-25T00:11:00+05:30"/>
<deceasedBoolean value="true"/>
<address>
<line value="534 Erewhon St "/>
<city value="PleasantVille"/>
<state value="Alabama"/>
<zip value="3999"/>
</address>
<address>
<line value="534 Erewhon St "/>
<city value="PleasantVille"/>
<state value="Alabama"/>
<zip value="3999"/>
</address>
<maritalStatus>
<text value="Single"/>
</maritalStatus>
<multipleBirthBoolean value="false"/>
<communication>
<text value="Spanish"/>
</communication>
<communication>
<text value="English"/>
</communication>
<communication>
<text value="Spanish"/>
</communication>
<communication>
<text value="English"/>
</communication>
<careProvider>
<reference value="Practitioner/131"/>
</careProvider>
<careProvider>
<reference value="Practitioner/132"/>
</careProvider>
<careProvider>
<reference value="Practitioner/133"/>
</careProvider>
<careProvider>
<reference value="Practitioner/134"/>
</careProvider>
<careProvider>
<reference value="Practitioner/143"/>
</careProvider>
</Patient>
</content>
<summary type="xhtml">
<div xmlns="http://www.w3.org/1999/xhtml">
<p>
<b>Generated Narrative</b>
</p><p>
<b>name</b>: </p>
<ul>
<li>Peter Chalmers </li>
<li>Peter Chalmers </li>
</ul><p>
<b>telecom</b>: </p>
<ul>
<li>ph: (03) 5555 6473</li>
<li>ph: -unknown-</li>
<li>peter.chalmers#healthintersections.com</li>
<li>ph: (03) 5555 6473</li>
<li>ph: -unknown-</li>
<li>peter.chalmers#healthintersections.com</li>
</ul><p>
<b>gender</b>: Male <span style="background: LightGoldenRodYellow ">(Details : { code "M" := "", given as "Male"})</span>
</p><p>
<b>birthDate</b>: 1974-11-25T00:11:00+05:30</p><p>
<b>deceased</b>: -1</p><p>
<b>address</b>: </p>
<ul>
<li>534 Erewhon St PleasantVille Alabama 3999 </li>
<li>534 Erewhon St PleasantVille Alabama 3999 </li>
</ul><p>
<b>maritalStatus</b>: Single <span style="background: LightGoldenRodYellow ">(Details )</span>
</p><p>
<b>multipleBirth</b>: 0</p><p>
<b>communication</b>: </p>
<ul>
<li>Spanish <span style="background: LightGoldenRodYellow ">(Details )</span>
</li>
<li>English <span style="background: LightGoldenRodYellow ">(Details )</span>
</li>
<li>Spanish <span style="background: LightGoldenRodYellow ">(Details )</span>
</li>
<li>English <span style="background: LightGoldenRodYellow ">(Details )</span>
</li>
</ul><p>
<b>careProvider</b>: </p>
<ul>
<li>
Practitioner/131
</li>
<li>
Practitioner/132
</li>
<li>
Practitioner/133
</li>
<li>
Practitioner/134
</li>
<li>
Practitioner/143
</li>
</ul>
</div>
</summary>
</entry>
</feed>

Use position of current node to access value of another node

I have an xml source that approximates a table layout (output from a program) - a is the table holder, b hold the column headings d, c are the rows and e are the row cells:
<?xml version="1.0" encoding="utf-16"?>
<a>
<b>
<d/>
<d/>
<d/>
</b>
<c>
<e/>
<e/>
<e/>
</c>
</a>
</xml>
I have written the following xsl:
<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="/">
<Lessons>
<xsl:for-each select="//c">
<xsl:call-template name="lesson" />
</xsl:for-each>
</Lessons>
</xsl:template>
<xsl:template name="lesson">
<Lesson>
<Teacher>
<xsl:value-of select="count(./preceding-sibling::*)+1" />
<xsl:value-of select="//b[count(./preceding-sibling::*)+1]" />
</Teacher>
</Lesson>
</xsl:template>
</xsl:stylesheet>
The first xsl:value-of of the Teacher element gives me the correct values. I would like the second xsl:value-of to return the value of the heading for that cell i.e. for the first e element that calls the template the first d element is returned and so on. However, it ouputs the value of all of the d elements.
Even if it is not entirely clear what you expect, I will try an answer.
As I understood you like to find the <d> element which has the same position than the <e> element.
This is either possible with getting the current position as a variable.
xsl:variable name ="pos" select="position()" />
<xsl:value-of select="//b/d[position() = $pos]/#id" />
or use count of preceding-sibling
<xsl:value-of select="//b/d[(count(current()/preceding-sibling::*)+1)]/#id" />
Update the part below is changed because of the comment from "George of all trades".
Be aware that the result of position()depends on the calling context.
For example following test xslt (version 1.0):
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<Lessons>
<!-- Wrong result with position -->
<xsl:for-each select="//c/e">
<xsl:call-template name="lesson" />
</xsl:for-each>
</Lessons>
<Lessons2>
<!-- Wonted result even with position -->
<xsl:for-each select="//c">
<xsl:for-each select="e">
<xsl:call-template name="lesson" />
</xsl:for-each>
</xsl:for-each>
</Lessons2>
</xsl:template>
<xsl:template name="lesson">
<Lesson>
<Teacher>
<xsl:value-of select="#id" />
<xsl:text>,</xsl:text>
<xsl:value-of select="count(./preceding-sibling::*)+1" />
<xsl:text>,</xsl:text>
<xsl:variable name ="pos" select="position()" />
<xsl:value-of select="$pos" />
<xsl:text>,</xsl:text>
<xsl:value-of select="//b/d[position() = $pos]/#id" />
<xsl:text>,</xsl:text>
<xsl:value-of select="//b/d[count(current()/preceding-sibling::*)+1]/#id" />
</Teacher>
</Lesson>
</xsl:template>
</xsl:stylesheet>
With this input:
<?xml version="1.0" encoding="utf-16"?>
<xml>
<a>
<b>
<d id="d1"/>
<d id="d2"/>
<d id="d3"/>
</b>
<c>
<e id="e1"/>
<e id="e2"/>
<e id="e3"/>
</c>
<c>
<e id="e21"/>
<e id="e22"/>
<e id="e23"/>
</c>
<c>
<e id="e21"/>
<e id="e22"/>
<e id="e23"/>
</c>
</a>
</xml>
Generates this output:
<Lessons>
<Lesson>
<Teacher>e1,1,1,d1,d1</Teacher>
</Lesson>
<Lesson>
<Teacher>e2,2,2,d2,d2</Teacher>
</Lesson>
<Lesson>
<Teacher>e3,3,3,d3,d3</Teacher>
</Lesson>
<Lesson>
<Teacher>e21,1,4,,d1</Teacher>
</Lesson>
<Lesson>
<Teacher>e22,2,5,,d2</Teacher>
</Lesson>
<Lesson>
<Teacher>e23,3,6,,d3</Teacher>
</Lesson>
<Lesson>
<Teacher>e21,1,7,,d1</Teacher>
</Lesson>
<Lesson>
<Teacher>e22,2,8,,d2</Teacher>
</Lesson>
<Lesson>
<Teacher>e23,3,9,,d3</Teacher>
</Lesson>
</Lessons><Lessons2>
<Lesson>
<Teacher>e1,1,1,d1,d1</Teacher>
</Lesson>
<Lesson>
<Teacher>e2,2,2,d2,d2</Teacher>
</Lesson>
<Lesson>
<Teacher>e3,3,3,d3,d3</Teacher>
</Lesson>
<Lesson>
<Teacher>e21,1,1,d1,d1</Teacher>
</Lesson>
<Lesson>
<Teacher>e22,2,2,d2,d2</Teacher>
</Lesson>
<Lesson>
<Teacher>e23,3,3,d3,d3</Teacher>
</Lesson>
<Lesson>
<Teacher>e21,1,1,d1,d1</Teacher>
</Lesson>
<Lesson>
<Teacher>e22,2,2,d2,d2</Teacher>
</Lesson>
<Lesson>
<Teacher>e23,3,3,d3,d3</Teacher>
</Lesson>
</Lessons2>

Select parent node with conditions in multiple children at unknown levels

In XPath, how to select the id of all <a> nodes that contain x=10 and y=100 in their children (which are at different levels)?
<root>
<a id="1">
<c>
<x>10</x>
<y>100</y>
</c>
</a>
<a id="4">
<c>
<c>
<x>10</x>
<y>100</y>
</c>
</c>
</a>
<a id="6">
<x>20</x>
<y>200</y>
</a>
<a id="7">
<x>10</x>
<y>300</y>
</a>
</root>
Something like this, I would imagine:
//a[.//x=10][.//y=100]/#id

Resources