/** * @throws SyntaxError When unknown operator is found */ public function toXpath() { $path = $this->selector->toXpath(); $attrib = $this->xpathAttrib(); $value = $this->value; if ($this->operator == 'exists') { $path->addCondition($attrib); } elseif ($this->operator == '=') { $path->addCondition(sprintf('%s = %s', $attrib, XPathExpr::xpathLiteral($value))); } elseif ($this->operator == '!=') { // FIXME: this seems like a weird hack... if ($value) { $path->addCondition(sprintf('not(%s) or %s != %s', $attrib, $attrib, XPathExpr::xpathLiteral($value))); } else { $path->addCondition(sprintf('%s != %s', $attrib, XPathExpr::xpathLiteral($value))); } // path.addCondition('%s != %s' % (attrib, xpathLiteral(value))) } elseif ($this->operator == '~=') { $path->addCondition(sprintf("contains(concat(' ', normalize-space(%s), ' '), %s)", $attrib, XPathExpr::xpathLiteral(' ' . $value . ' '))); } elseif ($this->operator == '|=') { // Weird, but true... $path->addCondition(sprintf('%s = %s or starts-with(%s, %s)', $attrib, XPathExpr::xpathLiteral($value), $attrib, XPathExpr::xpathLiteral($value . '-'))); } elseif ($this->operator == '^=') { $path->addCondition(sprintf('starts-with(%s, %s)', $attrib, XPathExpr::xpathLiteral($value))); } elseif ($this->operator == '$=') { // Oddly there is a starts-with in XPath 1.0, but not ends-with $path->addCondition(sprintf('substring(%s, string-length(%s)-%s) = %s', $attrib, $attrib, strlen($value) - 1, XPathExpr::xpathLiteral($value))); } elseif ($this->operator == '*=') { // FIXME: case sensitive? $path->addCondition(sprintf('contains(%s, %s)', $attrib, XPathExpr::xpathLiteral($value))); } else { throw new SyntaxError(sprintf('Unknown operator: %s', $this->operator)); } return $path; }
/** * Finds element by it's attribute(s) * * @static * @param $element * @param $attributes * @return string */ public static function find($element, array $attributes) { $operands = array(); foreach ($attributes as $attribute => $value) { if (is_int($attribute)) { $operands[] = '@' . $value; } else { $operands[] = '@' . $attribute . ' = ' . XPathExpr::xpathLiteral($value); } } return sprintf('//%s[%s]', $element, implode(' and ', $operands)); }
/** * * Updates the content of a xliff file with value for the matched trans id * * @return Boolean true on success * */ public function update(FileResource $resource, $id, $value) { if('' === $id) { throw new InvalidTranslationKeyException( sprintf('An empty key can not be used in "%s"', $resource->getResource()) ); } $document = $this->getDomDocument($resource); $xpath = $this->getDomXPath($document); $escapedId = XPathExpr::xpathLiteral($id); $sources = $xpath->query(sprintf('//xliff:trans-unit/xliff:source[. =%s]', $escapedId)); $updated = false; foreach ($sources as $source) { if (null === $target = $source->nextSibling) { $target = $document->createElement('target'); $source->parentNode->appendChild($target); } $target->nodeValue = $value; $updated = true; } if (false === $updated) { $nodeList = $xpath->evaluate('//xliff:trans-unit/@id[php:function("Knp\Bundle\TranslatorBundle\Dumper\dom_xpath_max", ., //xliff:trans-unit/@id)]'); $number = $nodeList->item(0)->value + 1; $node = $this->create($document, $id, $value, $number); $body = $xpath->query('//xliff:body')->item(0); $body->appendChild($node); } $this->checkErrors(); $result = $document->save($resource->getResource()); $this->checkErrors(); libxml_use_internal_errors($this->currentLibXmlErrorHandler); return false !== $result; }
/** * undocumented function * * @param XPathExpr $xpath * @param XPathExpr $expr * * @return XPathExpr */ protected function _xpath_not($xpath, $expr) { // everything for which not expr applies $expr = $expr->toXpath(); $cond = $expr->getCondition(); // FIXME: should I do something about element_path? $xpath->addCondition(sprintf('not(%s)', $cond)); return $xpath; }
/** * {@inheritDoc} */ public function toXpath() { $selXpath = $this->selector->toXpath(); $selXpath->addCondition(sprintf("contains(concat(' ', normalize-space(@class), ' '), %s)", XPathExpr::xpathLiteral(' ' . $this->className . ' '))); return $selXpath; }
/** * {@inheritDoc} */ public function toXpath() { $path = $this->selector->toXpath(); $path->addCondition(sprintf('@id = %s', XPathExpr::xpathLiteral($this->id))); return $path; }
protected function _xpath_contains($xpath, $expr) { // text content, minus tags, must contain expr if ($expr instanceof ElementNode) { $expr = $expr->formatElement(); } // FIXME: lower-case is only available with XPath 2 //$xpath->addCondition(sprintf('contains(lower-case(string(.)), %s)', XPathExpr::xpathLiteral(strtolower($expr)))); $xpath->addCondition(sprintf('contains(string(.), %s)', XPathExpr::xpathLiteral($expr))); // FIXME: Currently case insensitive matching doesn't seem to be happening return $xpath; }
/** * @dataProvider getXPathLiteralValues */ public function testXpathLiteral($value, $literal) { $this->assertEquals($literal, XPathExpr::xpathLiteral($value)); }
/** * Joins an XPath expression as an indirect adjacent of another. * * @param XPathExpr $xpath The parent XPath expression * @param NodeInterface $sub The indirect adjacent NodeInterface object * * @return XPathExpr An XPath instance */ protected function _xpath_indirect_adjacent($xpath, $sub) { // when sub comes somewhere after xpath as a sibling $xpath->join('/following-sibling::', $sub->toXpath()); return $xpath; }
/** * undocumented function * * @param XPathExpr $xpath The XPath expression * * @return XPathExpr The modified expression */ protected function xpath_empty($xpath) { $xpath->addCondition('not(*) and not(normalize-space())'); return $xpath; }