Is there a way to use filtering in E4X with hyphenated XML elements?

T

ten8ciousb

Tried this over at mozilla.dev.tech but didn't get any bites.
I know can return a list of nodes, but I want to get a specific
value.

given this xml
var phoneList = <table>
<row>
<COMPANY-NAME>DUNDER MIFFLIN</COMPANY-NAME>
<EMPLOYEE-NAME>Jim Halpert</EMPLOYEE-NAME>
<EMPLOYEE-PHONE>555-555-5555</EMPLOYEE-PHONE>
</row>
<row>
<COMPANY-NAME>INNOTECH</COMPANY-NAME>
<EMPLOYEE-NAME>Peter Gibbons</EMPLOYEE-NAME>
<EMPLOYEE-PHONE>555-444-4444</EMPLOYEE-PHONE>
</row>
<row>
<COMPANY-NAME>DUNDER MIFFLIN</COMPANY-NAME>
<EMPLOYEE-NAME>Dwight Schroot</EMPLOYEE-NAME>
<EMPLOYEE-PHONE>555-555-5550</EMPLOYEE-PHONE>
</row>

</table>;

if I want to get only the DUNDER MIFFLIN records, I can't use
phoneList..row.(COMPANY-NAME == "DUNDER MIFFLIN")
because the hyphen is used as a minus and I get an error about NAME
not
being defined or something.

I know that I can get a list of all the "COMPANY-NAME" nodes using
phoneList..row["COMPANY-NAME"];
-or-
phoneList...row.descendants("COMPANY-NAME");

those both return:
<COMPANY-NAME>DUNDER MIFFLIN</COMPANY-NAME>
<COMPANY-NAME>INNOTECH</COMPANY-NAME>
<COMPANY-NAME>DUNDER MIFFLIN</COMPANY-NAME>

Is there a way to filter the list? How can I just the DUNDER MIFFLIN
list? i.e., how can I do this?
phoneList..row.(COMPANY-NAME == "DUNDER MIFFLIN");

And to take it a step further. Just get the list of Dunder Mifflin
employees. How
phoneList..row.(COMPANY-NAME == "DUNDER MIFFLIN").EMPLOYEE-NAME;

and ultimately the phone number for a specific employee at a specific
company.
phoneList..row.(COMPANY-NAME == "DUNDER MIFFLIN" && EMPLOYEE-NAME ==
"Jim Halpert").EMPLOYEE-PHONE;


I have tried variations but haven't found one that let's me filter on
the content
 
T

Thomas 'PointedEars' Lahn

ten8ciousb said:
Tried this over at mozilla.dev.tech but didn't get any bites.
I know can return a list of nodes, but I want to get a specific
value.

given this xml
var phoneList = <table>
<row>
<COMPANY-NAME>DUNDER MIFFLIN</COMPANY-NAME>
<EMPLOYEE-NAME>Jim Halpert</EMPLOYEE-NAME>
<EMPLOYEE-PHONE>555-555-5555</EMPLOYEE-PHONE>
</row>
<row>
<COMPANY-NAME>INNOTECH</COMPANY-NAME>
<EMPLOYEE-NAME>Peter Gibbons</EMPLOYEE-NAME>
<EMPLOYEE-PHONE>555-444-4444</EMPLOYEE-PHONE>
</row>
<row>
<COMPANY-NAME>DUNDER MIFFLIN</COMPANY-NAME>
<EMPLOYEE-NAME>Dwight Schroot</EMPLOYEE-NAME>
<EMPLOYEE-PHONE>555-555-5550</EMPLOYEE-PHONE>
</row>

</table>;

if I want to get only the DUNDER MIFFLIN records, I can't use
phoneList..row.(COMPANY-NAME == "DUNDER MIFFLIN")
because the hyphen is used as a minus and I get an error about NAME
not being defined

Yes, `-' is an operator.
Is there a way to filter the list? How can I just the DUNDER MIFFLIN
list?

A verb here.
i.e., how can I do this?

With iteration over the nodes, or with XPath filtering and iteration over
the result. For example the latter:

var d = (new DOMParser()).parseFromString(phoneList, "text/xml");
if (!d) { /* gauntlet: error status */ }

var res = d.evaluate(
'//row/COMPANY-NAME[text() = "DUNDER MIFFLIN"]/following-sibling::*]',
d,
null,
...,
null);

// depending on ... as fourth argument, either
var e;
while ((e = res.iterateNext())
{
// ... e ...
}

// or
for (var i = 0, len = res.snapshotLength; i < len; i++)
{
// ... res.snapshotItem(i) ...
}

This assumes that the COMPANY-NAME element node is the first sibling. WFM
in Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.5) Gecko/2008122011
Iceweasel/3.0.5 (Debian-3.0.5-1).

You might want to use all-lowercase element types without hyphen in it
instead, like

<companies>
<company>
<name>Dunder Mifflin</name>
<employees>
<employee>
<name>Jim Halpert</name>
<phone>555-555-5555</phone>
</employee>
...
<employees>
</company>
...
</companies>

Or consider JSON.

RTFM, STFW:

<https://developer.mozilla.org/En/E4X>
<https://developer.mozilla.org/En/DOMParser>
<https://developer.mozilla.org/En/DOM/Document.evaluate>
<http://www.w3.org/TR/1999/REC-xpath-19991116/>
<http://json.org/>


HTH

PointedEars
 
T

ten8ciousb

First I apologize most sincerely for the incomplete sentences. I know
that can make it difficult to understand the questions when you have
to fill in the blanks.
Also thank you for the detailed reply and the RTFM and STFW
suggestions.
I guess I wasn't clear in my question.

With E4X, I can filter the results, saying I want a list of employees
where the value of company_name is "DUNDER MIFFLIN" like
var employees = phoneList..row.(company_name == "DUNDER
MIFFLIN").EMPLOYEE-NAME;

However, if the element contains a hyphen instead of an underscore,
i.e. company-name, that syntax won't work.
this: var employees = phoneList..row.(company-name == "DUNDER
MIFFLIN").EMPLOYEE-NAME;
results in a reference error name is undefined.

What I wanted to know is if there was a syntax in E4X for this type of
filtering with elements containing hyphens.
If I understand your response correctly, the answer is "No. But,
there are other ways to do it."
 
T

Thomas 'PointedEars' Lahn

ten8ciousb said:
With E4X, I can filter the results, saying I want a list of employees
where the value of company_name is "DUNDER MIFFLIN" like
var employees = phoneList..row.(company_name == "DUNDER
MIFFLIN").EMPLOYEE-NAME;

However, if the element contains a hyphen instead of an underscore,
i.e. company-name, that syntax won't work.
this: var employees = phoneList..row.(company-name == "DUNDER
MIFFLIN").EMPLOYEE-NAME;
results in a reference error name is undefined.

What I wanted to know is if there was a syntax in E4X for this type of
filtering with elements containing hyphens.
If I understand your response correctly, the answer is "No. But,
there are other ways to do it."

phoneList..row.descendants("COMPANY-NAME")

See ECMA-357. HTH and let us know your solution, please.


PointedEars
 
M

Martin Honnen

ten8ciousb said:
var phoneList = <table>
<row>
<COMPANY-NAME>DUNDER MIFFLIN</COMPANY-NAME>
<EMPLOYEE-NAME>Jim Halpert</EMPLOYEE-NAME>
<EMPLOYEE-PHONE>555-555-5555</EMPLOYEE-PHONE>
</row>
<row>
<COMPANY-NAME>INNOTECH</COMPANY-NAME>
<EMPLOYEE-NAME>Peter Gibbons</EMPLOYEE-NAME>
<EMPLOYEE-PHONE>555-444-4444</EMPLOYEE-PHONE>
</row>
<row>
<COMPANY-NAME>DUNDER MIFFLIN</COMPANY-NAME>
<EMPLOYEE-NAME>Dwight Schroot</EMPLOYEE-NAME>
<EMPLOYEE-PHONE>555-555-5550</EMPLOYEE-PHONE>
</row>

</table>;

if I want to get only the DUNDER MIFFLIN records, I can't use
phoneList..row.(COMPANY-NAME == "DUNDER MIFFLIN")
because the hyphen is used as a minus and I get an error about NAME
not
being defined or something.

I think with Spidermonkey's E4X implementation you can do

phoneList.row.(function::child('COMPANY-NAME') == 'DUNDER MIFFLIN')

I don't know whether Rhino's E4X has that special 'function::' namespace
to access methods.
 
T

Thomas 'PointedEars' Lahn

Martin said:
I think with Spidermonkey's E4X implementation you can do

phoneList.row.(function::child('COMPANY-NAME') == 'DUNDER MIFFLIN')

I don't know whether Rhino's E4X has that special 'function::' namespace
to access methods.

I was to suggest something along

[x for each (x in phoneList.row["COMPANY-NAME"]) if (x == "DUNDER MIFFLIN")]

But yours is better as it gets the rows. Unfortunately, I could not come up
with a filtering predicate that filters for element content:

phoneList.row["COMPANY-NAME"].(x == "DUNDER MIFFLIN")

Suggestions, except the above?


PointedEars
 
T

ten8ciousb

Thank you for the replies.

phoneList.row.(function::child('COMPANY-NAME') == 'DUNDER MIFFLIN')
does work if using SpiderMonkey.
It does not appear to work using Rhino. (Rhino 1.7 release 2) which
is what I'm trying to do.
just trying to open the script in the debugger give the error :
missing ( before function parameters.
js: thisRow = phoneList.row.(function::child('COMPANY-NAME') ==
'DUNDER MIFFLIN');
 
T

Thomas 'PointedEars' Lahn

ten8ciousb said:
Thank you for the replies.

You're welcome.
phoneList.row.(function::child('COMPANY-NAME') == 'DUNDER MIFFLIN')
does work if using SpiderMonkey.
It does not appear to work using Rhino. (Rhino 1.7 release 2) which
is what I'm trying to do.
just trying to open the script in the debugger give the error :
missing ( before function parameters.
js: thisRow = phoneList.row.(function::child('COMPANY-NAME') ==
'DUNDER MIFFLIN');

I have been thinking about my approach; try this:

var filtered = [
r for each (r in phoneList.row)
if (r["COMPANY-NAME"] == "DUNDER MIFFLIN")
];

Not standards-compliant (requires JavaScript 1.7 Array comprehension), but
it worksforme (in SpiderMonkey). Your Rhino version indicates it should
work there, too. If not, this should work:

var filtered = [];
for each (var r in phoneList.row)
{
if (r["COMPANY-NAME"] == "DUNDER MIFFLIN") filtered.push(r);
}


Regards,

PointedEars
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,044
Latest member
RonaldNen

Latest Threads

Top