* xmlXPathLangFunction: * @ctxt: the XPath Parser context * @nargs: the number of arguments * * Implement the lang() XPath function * boolean lang(string) * The lang function returns true or false depending on whether the * language of the context node as specified by xml:lang attributes * is the same as or is a sublanguage of the language specified by * the argument string. The lang
| 8478 | * value and ignoring case. |
| 8479 | */ |
| 8480 | void |
| 8481 | xmlXPathLangFunction(xmlXPathParserContextPtr ctxt, int nargs) { |
| 8482 | xmlXPathObjectPtr val; |
| 8483 | xmlNodePtr cur; |
| 8484 | xmlChar *theLang; |
| 8485 | const xmlChar *lang; |
| 8486 | int ret = 0; |
| 8487 | int i; |
| 8488 | |
| 8489 | CHECK_ARITY(1); |
| 8490 | CAST_TO_STRING; |
| 8491 | CHECK_TYPE(XPATH_STRING); |
| 8492 | val = valuePop(ctxt); |
| 8493 | lang = val->stringval; |
| 8494 | cur = ctxt->context->node; |
| 8495 | while (cur != NULL) { |
| 8496 | if (xmlNodeGetAttrValue(cur, BAD_CAST "lang", XML_XML_NAMESPACE, |
| 8497 | &theLang) < 0) |
| 8498 | xmlXPathPErrMemory(ctxt); |
| 8499 | if (theLang != NULL) |
| 8500 | break; |
| 8501 | cur = cur->parent; |
| 8502 | } |
| 8503 | if ((theLang != NULL) && (lang != NULL)) { |
| 8504 | for (i = 0;lang[i] != 0;i++) |
| 8505 | if (toupper(lang[i]) != toupper(theLang[i])) |
| 8506 | goto not_equal; |
| 8507 | if ((theLang[i] == 0) || (theLang[i] == '-')) |
| 8508 | ret = 1; |
| 8509 | } |
| 8510 | not_equal: |
| 8511 | if (theLang != NULL) |
| 8512 | xmlFree((void *)theLang); |
| 8513 | |
| 8514 | xmlXPathReleaseObject(ctxt->context, val); |
| 8515 | valuePush(ctxt, xmlXPathCacheNewBoolean(ctxt, ret)); |
| 8516 | } |
| 8517 | |
| 8518 | /** |
| 8519 | * xmlXPathNumberFunction: |
nothing calls this directly
no test coverage detected