473,385 Members | 1,338 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Match an attribute value in a set of possible values

Hi All,

given the source document:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<child>
<test id="1" name="first child"/>
</child>
<child>
<test id="2" name="second child"/>
</child>
<child>
<test id="3" name="third child"/>
</child>
</root>

I would suppress the the child elements that contain a test element
with the value of the id attribute in a list of known ids; for
instance, assuming that the list of ids to remove is {1,3}, I would
obtain the document:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<child>
<test id="2" name="second child"/>
</child>
</root>

where only the second child element is retained.

I'm only able to suppress a single child element using the following
XSL transform;

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="child[test[@id='1']]"/>
</xsl:stylesheet>

Is it possible to match and suppress multiple child elements whose ids
are contained in a given list ?

Since I'm invoking the transform from Java, I would like to set a
template parameter to the list of ids to be removed; e.g. as comma
delimited list, and write the last match condition as something like
this:

....
<xsl:param name="idToRemove" select="default" />
<xsl:template match="child[test[@id in $idsToRemove]]"/>
....

Note that I'm using XSLT 1.0, so I cannot leverage the enhancements of
XSLT 2.0, but I'm wondering if there is some trick to do the job; for
instance injecting the list of ids to remove into the same XSLT
document and then iterating over them and suppressing any matching
child element from the source document... maybe something like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:data="http://sample.array.parameters/data" version="1.0">
<xsl:output method="xml" indent="yes" />
<data:parameters>
<id>1</id>
<id>3</id>
</data:parameters>
<xsl:variable name="parameters-root"
select="document('')/*/data:parameters"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="child[test[@id in $parameters-root]]"/>
</xsl:stylesheet>

Thanks a lot for any suggestion

Regards,

Patrizio

Sep 1 '06 #1
5 1767


patrin wrote:
<xsl:template match="child[test[@id='1']]"/>
Well an or is possible in XPath 1.0

<xsl:template match="child[test[@id='1' or @id = '3']]"/>
--

Martin Honnen
http://JavaScript.FAQTs.com/
Sep 1 '06 #2

Martin Honnen wrote:
patrin wrote:
<xsl:template match="child[test[@id='1']]"/>

Well an or is possible in XPath 1.0

<xsl:template match="child[test[@id='1' or @id = '3']]"/>
--

Martin Honnen
http://JavaScript.FAQTs.com/
Thanks for the quick replay, but the list of ids to match is dynamyc
and I know it only from Java code, where it is stored into a String
arrray:

String[] idsToRemove = {1,3,...};

and I would like to pass it to the Transformer, invoking the method:

setParameter("idsToRemove", idsToRemove);

so that the XSLT should remove all the child elements whose test
subelement has an id with any of the values contained in the
idsToRemove array.

Is it possible to do this with XSLT 1.0 ? or can you suggest an
alternative way to solve the problem ?

Thanks again for your help

Regards,

Patrizio

Sep 1 '06 #3
patrin wrote:
setParameter("idsToRemove", idsToRemove);
Well, you're unlikely to be able to pass in an array of strings and do
anything useful with it except (maybe) pass it back out to an extension
function. Xalan, for example, will treat that as a "non-XSLT type".

I'd suggest reformatting the data as a single string, which most
processors should treat as an XSLT string value, and then doing string
manipulation to check if the ID is contained in that list. I did a
quick-and-dirty version of that in my styling-stylesheets article; since
it was just an illustration I didn't make it highly robust but you could
make it stronger by checking delimiters.

Alternatively, some processors (again, Xalan is one of these) may let
you pass in a DOM node and have XSLT treat it as a node-set. If you
construct a tree where one element has each of the values, you could
then do an XSLT node-set comparison (does any node in one set equal any
node in the other set). The stylesheet would be cleaner, but the
preparation would be more complex. I'm not sure how portable this
approach would be; the TrAX APIs don't make any particular promises
about how non-string parameters will be processed.

Alternatively: Build that nodes-I'm-interested-in XML document as text,
and put it somewhere that the stylesheet can access via the document()
function. Less efficient, but it gives you the simple "does anything
equal" syntax in the stylesheet, and it may be more portable than
relying on the API to do something useful with Nodes.
--
Joe Kesselman / Beware the fury of a patient man. -- John Dryden
Sep 1 '06 #4


patrin wrote:

Thanks for the quick replay, but the list of ids to match is dynamyc
and I know it only from Java code, where it is stored into a String
arrray:

String[] idsToRemove = {1,3,...};

and I would like to pass it to the Transformer, invoking the method:

setParameter("idsToRemove", idsToRemove);

so that the XSLT should remove all the child elements whose test
subelement has an id with any of the values contained in the
idsToRemove array.

Is it possible to do this with XSLT 1.0 ?
I guess there are two approaches, one that might be processor dependent
where you need to look at the documentation of the XSLT processor what
kind of types you can pass in with setParameter:

The setParameter method
<http://java.sun.com/j2se/1.5.0/docs/api/javax/xml/transform/Transformer.html#setParameter(java.lang.String,%20 java.lang.Object)>
as the second argument takes any object so it might well be that it
works to pass in a Source (e.g. DOMSource or SAXSource or StreamSource)
there as well. But details depend on the XSLT processor, I don't think I
have tried that so far with Saxon or Xalan.
The second approach would take the XSLT stylesheet as an XML document
and change it as needed depending on your idsToRemove before the
stylesheet is used for the transformation.
--

Martin Honnen
http://JavaScript.FAQTs.com/
Sep 1 '06 #5
As others have commented, there are different way to structure the
externally passed parameter or even to modify dynamically the stylesheet, so
that passing a parameter will not be necessary.

But your initial question was how to find that the @id attribute of the
current element is part of ids list, encoded as a coma-delimited string. One
way to determine this is using the following XPath 1.0 expression:

contains($idList, concat(' ', @id, ','))

This will work if every id in the list starts with at least one space and is
followed immediately by a coma. The global parameter itself will have to be
produced and passed to the stylesheet by an implementation-dependent
component -- as this varies for different XSLT processors, one needs to
study the documentation of the specific XSLT processor used in order to
understand how this should be done.

Certainly there are ways to perform more precise tokenization (one example
is the tokenization implemented in the FXSL library), but this simple
solution is probably good just for a start.

Cheers,
Dimitre Novatchev

"patrin" <pa****************@googlemail.comwrote in message
news:11**********************@m73g2000cwd.googlegr oups.com...
Hi All,

given the source document:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<child>
<test id="1" name="first child"/>
</child>
<child>
<test id="2" name="second child"/>
</child>
<child>
<test id="3" name="third child"/>
</child>
</root>

I would suppress the the child elements that contain a test element
with the value of the id attribute in a list of known ids; for
instance, assuming that the list of ids to remove is {1,3}, I would
obtain the document:

<?xml version="1.0" encoding="UTF-8"?>
<root>
<child>
<test id="2" name="second child"/>
</child>
</root>

where only the second child element is retained.

I'm only able to suppress a single child element using the following
XSL transform;

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="child[test[@id='1']]"/>
</xsl:stylesheet>

Is it possible to match and suppress multiple child elements whose ids
are contained in a given list ?

Since I'm invoking the transform from Java, I would like to set a
template parameter to the list of ids to be removed; e.g. as comma
delimited list, and write the last match condition as something like
this:

...
<xsl:param name="idToRemove" select="default" />
<xsl:template match="child[test[@id in $idsToRemove]]"/>
...

Note that I'm using XSLT 1.0, so I cannot leverage the enhancements of
XSLT 2.0, but I'm wondering if there is some trick to do the job; for
instance injecting the list of ids to remove into the same XSLT
document and then iterating over them and suppressing any matching
child element from the source document... maybe something like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:data="http://sample.array.parameters/data" version="1.0">
<xsl:output method="xml" indent="yes" />
<data:parameters>
<id>1</id>
<id>3</id>
</data:parameters>
<xsl:variable name="parameters-root"
select="document('')/*/data:parameters"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="child[test[@id in $parameters-root]]"/>
</xsl:stylesheet>

Thanks a lot for any suggestion

Regards,

Patrizio

Sep 2 '06 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Ravi | last post by:
My XML looks like: <role type="Joker"> <Profile id="13">ABC_Organization</Profile> </role> My XSL looks like: <xsl:variable name="prefix">profile_joker_</xsl:variable> <xsl:variable...
0
by: Carl | last post by:
Hi, I have found a way to map attributes (columns) to column headings. But this runs really slow. Is there a way to improve it? Thanks, Carl <?xml version="1.0" encoding="utf-8" ?>...
0
by: Ingrid | last post by:
Am I right in thinking that datatyping at element level ie <xs:element name="num" type="xs:integer"> and specifying a choice of attribute values ie <xs:attribute name="kind"> <xs:simpleType>...
5
by: Gerald Aichholzer | last post by:
Hello NG, I have an XHMTL-file and would like to replace attribute values using XSLT. The XHTML-file contains the following code: <applet code="MyApplet/MyApplet.class"...
2
by: Bill Cohagan | last post by:
In my app I'm validating an XML file against an XSD which contains several attribute default value specifications. I'm performing the validation via an xml document load() using a...
10
by: Jon Noring | last post by:
Out of curiosity, may a CDATA section appear within an attribute value with datatype CDATA? And if so, how about other attribute value datatypes which accept the XML markup characters? To me,...
5
by: Soledad Vel | last post by:
Hi All, i write this code: var sliderwidth=100; var sliderheight = 100; var div1 = document.createElement('div'); div1.setAttribute('id','d5'); div1.setAttribute('style',...
4
by: rossable | last post by:
The issue is that I need to place an a tag around an image in a .xslt file. Structurally and logically I don't see why this isn't working. <td class="bluecontent_head10d" colSpan="4"> <div...
3
markmcgookin
by: markmcgookin | last post by:
Hi, I have the following XML <AnswerList xmlns="http://tempuri.org/ALPS_Assessmentv1p1_RESCO_Schema.xsd"> <DateTimeLastSaved>12:12:12 1900</DateTimeLastSaved> <UserName>Bob</UserName>...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.