Project

Profile

Help

Bug #6525

open

XdmNode::getChildren() returns always null - Should be array

Added by Fernando J. Martin 4 months ago. Updated 28 days ago.

Status:
New
Priority:
Normal
Category:
-
Start date:
2024-09-05
Due date:
% Done:

0%

Estimated time:
Applies to branch:
Fix Committed on Branch:
Fixed in Maintenance Release:
Found in version:
Fixed in version:
SaxonC Languages:
SaxonC Platforms:
All
SaxonC Architecture:

Description

Version/Platform:
SaxonC-EE 12.5 (compiled in Linux)

Summary:
After validating an XSD schema and getting the report, XdmNode::getChildren() returns always null even though there are errors (nodes).

Reproduce Steps:
Executing this code you'll get comparison between getChildren() which returns NULL vs. getting first node's child XdmNode and grabbing attributes and values manually.

<?php

require 'vendor/autoload.php';

use Saxon\SaxonProcessor;

putenv('SAXONC_HOME=.saxon');

$xsdSchema = 'schema.xsd';
$schemaString = '<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="person">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="name" type="xs:string" />
        <xs:element name="age" type="xs:integer" />
        <xs:element name="email" type="xs:string" />
      </xs:sequence>
    </xs:complexType>
  </xs:element>
</xs:schema>';
file_put_contents($xsdSchema, $schemaString);

$xmlFile = 'payload.xml';
$xmlString = '<?xml version="1.0" encoding="UTF-8"?>
<person>
  <name>Jane Doe</name>
  <age>twenty-five</age>
  <email>jane.doe@example</email>
</person>';
file_put_contents($xmlFile, $xmlString);

$processor = new SaxonProcessor(true);
$validator = $processor->newSchemaValidator();
$validator->registerSchemaFromFile($xsdSchema);
$validator->setProperty('report-node', true);

try {
    $validator->validate($xmlFile);
} catch (Exception $e) {

    $report = $validator->getValidationReport();
    echo '=============================='.PHP_EOL;
    echo '=== $report->getChildren() ==='.PHP_EOL;
    echo '=============================='.PHP_EOL;
    var_dump($report->getChildren());
    echo '=============================='.PHP_EOL;

    echo PHP_EOL . PHP_EOL;

    echo '=========================================='.PHP_EOL;
    echo '=== $report->getChildNode(0) iteration ==='.PHP_EOL;
    echo '=========================================='.PHP_EOL;
    $xmlDocument = $processor->parseXmlFromFile($xmlFile);
    $xpathProcessor = $processor->newXPathProcessor();
    $xpathProcessor->setContextItem($xmlDocument);
    $reportNode = $report->getChildNode(0);

    for ($i = 0; $i < $reportNode->getChildCount(); $i++) {
        $node = $reportNode->getChildNode($i);
        $attributes = $node->getAttributeNodes();

        if (!$attributes) {
            continue;
        }

        $message = $node->getStringValue();
        $nodeName = $node->getNodeName();
        $nodeValue = $node->getStringValue();
        preg_match('/<([^<>]+)>/', $message, $matches);
        $extracted = $matches[1];

        /** @var \Saxon\XdmNode $attributeNode */
        foreach ($node->getAttributeNodes() as $attributeNode) {
            $message = $node->getStringValue();
            match ($attributeNode->getNodeName()) {
                'line' => $line = $attributeNode->getStringValue(),
                'column' => $column = $attributeNode->getStringValue(),
                'path' => $path = $attributeNode->getStringValue(),
                default => null,
            };
        }
        $invalidNode = $xpathProcessor->evaluateSingle($path);
        $invalidNodeValue = $invalidNode?->getStringValue();

        echo "Message: $message".PHP_EOL;
        echo "Node Name: $nodeName".PHP_EOL;
        echo "Node Value: $nodeValue".PHP_EOL;
        echo 'Invalid element: '.$extracted.PHP_EOL;
        echo 'Invalid Value: '.$invalidNodeValue.PHP_EOL;
        echo 'Line: '.$line.PHP_EOL;
        echo 'Column: '.$column.PHP_EOL;
        echo 'Path: '.$path.PHP_EOL;
    }
}

Outcome of the previous code:

==============================
=== $report->getChildren() ===
==============================
NULL
==============================


==========================================
=== $report->getChildNode(0) iteration ===
==========================================
Message: The content "twenty-five" of element <age> does not match the required simple type. Cannot convert string "twenty-five" to an integer: contains a character 't'(#x74) that is not a digit
Node Name: Q{http://saxon.sf.net/ns/validation}error
Node Value: The content "twenty-five" of element <age> does not match the required simple type. Cannot convert string "twenty-five" to an integer: contains a character 't'(#x74) that is not a digit
Invalid element: age
Invalid Value: twenty-five
Line: 4
Column: 25
Path: /Q{}person[1]/Q{}age[1]

Please register to edit this issue

Also available in: Atom PDF