XSLT: How to select siblings with a condition
I have the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<thesaurus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<term id="01">
<name>
<value>green</value>
</name>
<info>
<ref rid="12" obj-type="Building" />
</info>
<info>
<ref rid="13" obj-type="House" />
</info>
<info>
<ref rid="14" obj-type="Apartment"/>
</info>
</term>
<term id="02">
<name>
<value>blue</value>
</name>
<info>
<ref rid="24" obj-type="Unknown"/>
</info>
<info>
<ref rid="26" obj-type="Unknown"/>
</info>
<info>
<ref rid="29" obj-type="Unknown"/>
</info>
</term>
<term id="03">
<name>
<value>yellow</value>
</name>
</term>
<term id="04">
<name>
<value>red</value>
</name>
<info>
<ref rid="40" obj-type="Hotel"/>
</info>
<info>
<ref rid="41" obj-type="Building"/>
</info>
<info>
<ref rid="43" obj-type="House"/>
</info>
</term>
<term id="05">
<name>
<value>purple</value>
</name>
</term>
<term id="06">
<name>
<value>magenta</value>
</name>
<info>
<ref rid="60" obj-type="Building"/>
</info>
<info>
<ref rid="62" obj-type="Unknown"/>
</info>
<info>
<ref rid="64" obj-type="House"/>
</info>
</term>
</thesaurus>
What I want is this:
1) Select all
<term>
tags that without an<info>
tag. This is
already accomplished with the first apply-templates:
select="term[not(info)]" in the XSLT below.
2) Select all
<term>
tags when its<ref>
tag contains an
obj-type="Unknown"
alone or multiple times, but don't select it if
it's surrounded byobj-types
with values different than "Unknown"
(like Building or House).
*** Inside an
<info>
tag, when havingobj-type
siblings with other values,
it takes at least one value of 'Unknown' for the<term>
tag to not
be selected.
If the XSLT works well, the tags selected will be:
02, 03, 05
where:
01 won't be selected because it contains
<info>
tags, and none of those tags has a obj-type='Unknown'
02 will be selected because there are three multiple values of 'Unknown', and
no other values different than 'Unknown'
03 will be selected because it does not contains
<info>
tags
04 won't be selected because it contains
<info>
tags withobj-type
values different than 'Unknown'.
05 will be selected because there are no info tags.
06 won't be selected because although there is one value of 'Unknown',
all the other<ref>
siblings have a valueobj-type
different than 'Unknown'.
*** REMEMBER: Inside an
<info>
tag, when havingobj-type
siblings with other values, it takes at least one value of
'Unknown' for the<term>
tag to not be selected.
I'm using the XSLT below. With the first apply-templates I can select all the tags without an <info>
tag.
With the second apply-templates I can select all the <term>
tags that contain a <ref>
tag with an obj-type="Unknown"
, but I don't know how to tell the XSLT that if there are obj-types with a different value, don't select the corresponding <term>
tag.
I tried to use a for-each and a conditional, to iterate through all the <ref>
children and check whether one of the siblings had a different value than 'Unknown' to not select its <term>
parent, but to no avail.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="text"/>
<xsl:template match="/thesaurus">
<xsl:apply-templates select="term[not(info)]"/>
<xsl:apply-templates select="term[info/ref[@obj-type='Unknown']]"/>
</xsl:template>
<xsl:template match="term">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="term[info/ref]">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
I hope it's clear.
xml xslt
add a comment |
I have the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<thesaurus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<term id="01">
<name>
<value>green</value>
</name>
<info>
<ref rid="12" obj-type="Building" />
</info>
<info>
<ref rid="13" obj-type="House" />
</info>
<info>
<ref rid="14" obj-type="Apartment"/>
</info>
</term>
<term id="02">
<name>
<value>blue</value>
</name>
<info>
<ref rid="24" obj-type="Unknown"/>
</info>
<info>
<ref rid="26" obj-type="Unknown"/>
</info>
<info>
<ref rid="29" obj-type="Unknown"/>
</info>
</term>
<term id="03">
<name>
<value>yellow</value>
</name>
</term>
<term id="04">
<name>
<value>red</value>
</name>
<info>
<ref rid="40" obj-type="Hotel"/>
</info>
<info>
<ref rid="41" obj-type="Building"/>
</info>
<info>
<ref rid="43" obj-type="House"/>
</info>
</term>
<term id="05">
<name>
<value>purple</value>
</name>
</term>
<term id="06">
<name>
<value>magenta</value>
</name>
<info>
<ref rid="60" obj-type="Building"/>
</info>
<info>
<ref rid="62" obj-type="Unknown"/>
</info>
<info>
<ref rid="64" obj-type="House"/>
</info>
</term>
</thesaurus>
What I want is this:
1) Select all
<term>
tags that without an<info>
tag. This is
already accomplished with the first apply-templates:
select="term[not(info)]" in the XSLT below.
2) Select all
<term>
tags when its<ref>
tag contains an
obj-type="Unknown"
alone or multiple times, but don't select it if
it's surrounded byobj-types
with values different than "Unknown"
(like Building or House).
*** Inside an
<info>
tag, when havingobj-type
siblings with other values,
it takes at least one value of 'Unknown' for the<term>
tag to not
be selected.
If the XSLT works well, the tags selected will be:
02, 03, 05
where:
01 won't be selected because it contains
<info>
tags, and none of those tags has a obj-type='Unknown'
02 will be selected because there are three multiple values of 'Unknown', and
no other values different than 'Unknown'
03 will be selected because it does not contains
<info>
tags
04 won't be selected because it contains
<info>
tags withobj-type
values different than 'Unknown'.
05 will be selected because there are no info tags.
06 won't be selected because although there is one value of 'Unknown',
all the other<ref>
siblings have a valueobj-type
different than 'Unknown'.
*** REMEMBER: Inside an
<info>
tag, when havingobj-type
siblings with other values, it takes at least one value of
'Unknown' for the<term>
tag to not be selected.
I'm using the XSLT below. With the first apply-templates I can select all the tags without an <info>
tag.
With the second apply-templates I can select all the <term>
tags that contain a <ref>
tag with an obj-type="Unknown"
, but I don't know how to tell the XSLT that if there are obj-types with a different value, don't select the corresponding <term>
tag.
I tried to use a for-each and a conditional, to iterate through all the <ref>
children and check whether one of the siblings had a different value than 'Unknown' to not select its <term>
parent, but to no avail.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="text"/>
<xsl:template match="/thesaurus">
<xsl:apply-templates select="term[not(info)]"/>
<xsl:apply-templates select="term[info/ref[@obj-type='Unknown']]"/>
</xsl:template>
<xsl:template match="term">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="term[info/ref]">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
I hope it's clear.
xml xslt
add a comment |
I have the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<thesaurus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<term id="01">
<name>
<value>green</value>
</name>
<info>
<ref rid="12" obj-type="Building" />
</info>
<info>
<ref rid="13" obj-type="House" />
</info>
<info>
<ref rid="14" obj-type="Apartment"/>
</info>
</term>
<term id="02">
<name>
<value>blue</value>
</name>
<info>
<ref rid="24" obj-type="Unknown"/>
</info>
<info>
<ref rid="26" obj-type="Unknown"/>
</info>
<info>
<ref rid="29" obj-type="Unknown"/>
</info>
</term>
<term id="03">
<name>
<value>yellow</value>
</name>
</term>
<term id="04">
<name>
<value>red</value>
</name>
<info>
<ref rid="40" obj-type="Hotel"/>
</info>
<info>
<ref rid="41" obj-type="Building"/>
</info>
<info>
<ref rid="43" obj-type="House"/>
</info>
</term>
<term id="05">
<name>
<value>purple</value>
</name>
</term>
<term id="06">
<name>
<value>magenta</value>
</name>
<info>
<ref rid="60" obj-type="Building"/>
</info>
<info>
<ref rid="62" obj-type="Unknown"/>
</info>
<info>
<ref rid="64" obj-type="House"/>
</info>
</term>
</thesaurus>
What I want is this:
1) Select all
<term>
tags that without an<info>
tag. This is
already accomplished with the first apply-templates:
select="term[not(info)]" in the XSLT below.
2) Select all
<term>
tags when its<ref>
tag contains an
obj-type="Unknown"
alone or multiple times, but don't select it if
it's surrounded byobj-types
with values different than "Unknown"
(like Building or House).
*** Inside an
<info>
tag, when havingobj-type
siblings with other values,
it takes at least one value of 'Unknown' for the<term>
tag to not
be selected.
If the XSLT works well, the tags selected will be:
02, 03, 05
where:
01 won't be selected because it contains
<info>
tags, and none of those tags has a obj-type='Unknown'
02 will be selected because there are three multiple values of 'Unknown', and
no other values different than 'Unknown'
03 will be selected because it does not contains
<info>
tags
04 won't be selected because it contains
<info>
tags withobj-type
values different than 'Unknown'.
05 will be selected because there are no info tags.
06 won't be selected because although there is one value of 'Unknown',
all the other<ref>
siblings have a valueobj-type
different than 'Unknown'.
*** REMEMBER: Inside an
<info>
tag, when havingobj-type
siblings with other values, it takes at least one value of
'Unknown' for the<term>
tag to not be selected.
I'm using the XSLT below. With the first apply-templates I can select all the tags without an <info>
tag.
With the second apply-templates I can select all the <term>
tags that contain a <ref>
tag with an obj-type="Unknown"
, but I don't know how to tell the XSLT that if there are obj-types with a different value, don't select the corresponding <term>
tag.
I tried to use a for-each and a conditional, to iterate through all the <ref>
children and check whether one of the siblings had a different value than 'Unknown' to not select its <term>
parent, but to no avail.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="text"/>
<xsl:template match="/thesaurus">
<xsl:apply-templates select="term[not(info)]"/>
<xsl:apply-templates select="term[info/ref[@obj-type='Unknown']]"/>
</xsl:template>
<xsl:template match="term">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="term[info/ref]">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
I hope it's clear.
xml xslt
I have the following XML:
<?xml version="1.0" encoding="UTF-8"?>
<thesaurus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<term id="01">
<name>
<value>green</value>
</name>
<info>
<ref rid="12" obj-type="Building" />
</info>
<info>
<ref rid="13" obj-type="House" />
</info>
<info>
<ref rid="14" obj-type="Apartment"/>
</info>
</term>
<term id="02">
<name>
<value>blue</value>
</name>
<info>
<ref rid="24" obj-type="Unknown"/>
</info>
<info>
<ref rid="26" obj-type="Unknown"/>
</info>
<info>
<ref rid="29" obj-type="Unknown"/>
</info>
</term>
<term id="03">
<name>
<value>yellow</value>
</name>
</term>
<term id="04">
<name>
<value>red</value>
</name>
<info>
<ref rid="40" obj-type="Hotel"/>
</info>
<info>
<ref rid="41" obj-type="Building"/>
</info>
<info>
<ref rid="43" obj-type="House"/>
</info>
</term>
<term id="05">
<name>
<value>purple</value>
</name>
</term>
<term id="06">
<name>
<value>magenta</value>
</name>
<info>
<ref rid="60" obj-type="Building"/>
</info>
<info>
<ref rid="62" obj-type="Unknown"/>
</info>
<info>
<ref rid="64" obj-type="House"/>
</info>
</term>
</thesaurus>
What I want is this:
1) Select all
<term>
tags that without an<info>
tag. This is
already accomplished with the first apply-templates:
select="term[not(info)]" in the XSLT below.
2) Select all
<term>
tags when its<ref>
tag contains an
obj-type="Unknown"
alone or multiple times, but don't select it if
it's surrounded byobj-types
with values different than "Unknown"
(like Building or House).
*** Inside an
<info>
tag, when havingobj-type
siblings with other values,
it takes at least one value of 'Unknown' for the<term>
tag to not
be selected.
If the XSLT works well, the tags selected will be:
02, 03, 05
where:
01 won't be selected because it contains
<info>
tags, and none of those tags has a obj-type='Unknown'
02 will be selected because there are three multiple values of 'Unknown', and
no other values different than 'Unknown'
03 will be selected because it does not contains
<info>
tags
04 won't be selected because it contains
<info>
tags withobj-type
values different than 'Unknown'.
05 will be selected because there are no info tags.
06 won't be selected because although there is one value of 'Unknown',
all the other<ref>
siblings have a valueobj-type
different than 'Unknown'.
*** REMEMBER: Inside an
<info>
tag, when havingobj-type
siblings with other values, it takes at least one value of
'Unknown' for the<term>
tag to not be selected.
I'm using the XSLT below. With the first apply-templates I can select all the tags without an <info>
tag.
With the second apply-templates I can select all the <term>
tags that contain a <ref>
tag with an obj-type="Unknown"
, but I don't know how to tell the XSLT that if there are obj-types with a different value, don't select the corresponding <term>
tag.
I tried to use a for-each and a conditional, to iterate through all the <ref>
children and check whether one of the siblings had a different value than 'Unknown' to not select its <term>
parent, but to no avail.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="text"/>
<xsl:template match="/thesaurus">
<xsl:apply-templates select="term[not(info)]"/>
<xsl:apply-templates select="term[info/ref[@obj-type='Unknown']]"/>
</xsl:template>
<xsl:template match="term">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="term[info/ref]">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
I hope it's clear.
xml xslt
xml xslt
asked Nov 15 '18 at 16:11
mistervelamistervela
4910
4910
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
You could try selecting the terms who doesn't contain something other than Unknown
<xsl:apply-templates select="term[not(info/ref[@obj-type!='Unknown'])]"/>
Or adding an if statement in your term[info/ref]
template
<xsl:template match="term[info/ref]">
<xsl:if test="not(info/ref[@obj-type!='Unknown'])">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
It works. Thank you so much for taking your time to go through this code. I knew it was something that simple. I tried to use an IF but couldn't properly construct it in XSLT terms. Thanks again.
– mistervela
Nov 16 '18 at 10:11
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53323550%2fxslt-how-to-select-siblings-with-a-condition%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
You could try selecting the terms who doesn't contain something other than Unknown
<xsl:apply-templates select="term[not(info/ref[@obj-type!='Unknown'])]"/>
Or adding an if statement in your term[info/ref]
template
<xsl:template match="term[info/ref]">
<xsl:if test="not(info/ref[@obj-type!='Unknown'])">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
It works. Thank you so much for taking your time to go through this code. I knew it was something that simple. I tried to use an IF but couldn't properly construct it in XSLT terms. Thanks again.
– mistervela
Nov 16 '18 at 10:11
add a comment |
You could try selecting the terms who doesn't contain something other than Unknown
<xsl:apply-templates select="term[not(info/ref[@obj-type!='Unknown'])]"/>
Or adding an if statement in your term[info/ref]
template
<xsl:template match="term[info/ref]">
<xsl:if test="not(info/ref[@obj-type!='Unknown'])">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
It works. Thank you so much for taking your time to go through this code. I knew it was something that simple. I tried to use an IF but couldn't properly construct it in XSLT terms. Thanks again.
– mistervela
Nov 16 '18 at 10:11
add a comment |
You could try selecting the terms who doesn't contain something other than Unknown
<xsl:apply-templates select="term[not(info/ref[@obj-type!='Unknown'])]"/>
Or adding an if statement in your term[info/ref]
template
<xsl:template match="term[info/ref]">
<xsl:if test="not(info/ref[@obj-type!='Unknown'])">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
You could try selecting the terms who doesn't contain something other than Unknown
<xsl:apply-templates select="term[not(info/ref[@obj-type!='Unknown'])]"/>
Or adding an if statement in your term[info/ref]
template
<xsl:template match="term[info/ref]">
<xsl:if test="not(info/ref[@obj-type!='Unknown'])">
<xsl:value-of select="@id"/>
<xsl:text>,</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>,</xsl:text>
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
answered Nov 15 '18 at 17:38
NeskuNesku
4231412
4231412
It works. Thank you so much for taking your time to go through this code. I knew it was something that simple. I tried to use an IF but couldn't properly construct it in XSLT terms. Thanks again.
– mistervela
Nov 16 '18 at 10:11
add a comment |
It works. Thank you so much for taking your time to go through this code. I knew it was something that simple. I tried to use an IF but couldn't properly construct it in XSLT terms. Thanks again.
– mistervela
Nov 16 '18 at 10:11
It works. Thank you so much for taking your time to go through this code. I knew it was something that simple. I tried to use an IF but couldn't properly construct it in XSLT terms. Thanks again.
– mistervela
Nov 16 '18 at 10:11
It works. Thank you so much for taking your time to go through this code. I knew it was something that simple. I tried to use an IF but couldn't properly construct it in XSLT terms. Thanks again.
– mistervela
Nov 16 '18 at 10:11
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53323550%2fxslt-how-to-select-siblings-with-a-condition%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown