drwn65609 2015-09-11 15:36
浏览 68
已采纳

为什么DOMDocument :: schemaValidate()在相同的XML和XSD文件上的执行时间有时会比平时高得多?

It is extrange that a default class method fails that way, sometimes, even when the arguments passed to the method are the same that usualy takes a fraction of second.

Maximum execution time of 30 seconds exceeded in script_path on line script_line_number

In that exact line:

$result = $DOMDocument -> schemaValidate($schemaPath);

$DOMDocument is always the same. And it only references parts of the same XML with ID atrtibutes. It does not have any URL like attribute, besides Algorith and xmlns ones, which by nature does not call anyresource from anywhere, and we are talking about DOMDocument class of PHP and the XML starndards.

$schemaPath is always the same, and it is pointing to a server local XSD file, which is always there, before, and after the validation attempt, either it is successful or not. The schema is only pointing to other local xsd files, located in the same folder i.e. <xs:include schemaLocation="schema2.xsd"/>

The only possible answer I can think of, is that the XSD file is located by the method but for some reason it cannot be read, because the disc is busy.

What could be causing the execution of the method take so long?

What measures should be taken to prevent the error to happen besides increasing the maximum execution time limit of PHP?

The XML and the XSD files are pretty small, in fact the exact same XML and XSD usually takes less than ~ 0.1 seconds to validate, but a very few times (~ 1 out of 1000) the execution time exeeds 30 seconds.


EDIT

I isolated the problem so I post a samples.

Schema.xsd:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema targetNamespace="http://www.foo.bar/Car" xmlns:SiiDte="http://www.foo.bar/Car" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:include schemaLocation="schema2.xsd"/>
    <xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsignature_v10.xsd"/><!-- just the standar signature schema -->
    <xs:element name="ROOT" type="SiiDte:ROOTDefType"/>
    <xs:complexType name="ROOTDefType">
        <xs:sequence>
            <xs:element name="Element"></xs:element>
            <xs:element ref="ds:Signature">
                <xs:annotation>
                    <xs:documentation>Firma Digital sobre Documento</xs:documentation>
                </xs:annotation>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="version" type="xs:decimal" use="required" fixed="1.0"/>
    </xs:complexType>
</xs:schema>

Schema2.xsd:

<xs:schema targetNamespace="http://www.foo.bar/Car" xmlns:ns1="http://www.foo.bar/Car" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
    <xs:simpleType name="MOOType">
        <xs:restriction base="xs:positiveInteger">
            <xs:enumeration value="1"/>
            <xs:enumeration value="2"/>
            <xs:enumeration value="3"/>
        </xs:restriction>
    </xs:simpleType>
</xs:schema>

Code:

// ... a bunch of ther code...

$XML =
    '<?xml version="1.0"?>
    <ROOT xmlns="http://www.foo.bar/Car" version="1.0">
        <Element ID="A1">hello</Element>
        <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
            <SignedInfo>
                <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
                <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
                <Reference URI="#A1">
                    <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                    <DigestValue>base64string</DigestValue>
                </Reference>
            </SignedInfo>
            <SignatureValue>base64string</SignatureValue>
            <KeyInfo>
                <KeyValue>
                    <RSAKeyValue>
                        <Modulus>base64string</Modulus>
                        <Exponent>AQAB</Exponent>
                    </RSAKeyValue>
                </KeyValue>
                <X509Data>
                    <X509Certificate>base64string</X509Certificate>
                </X509Data>
            </KeyInfo>
        </Signature>
    </ROOT>'
;

$DD = new DOMDocument();
$DD -> loadXML($XML);
$i = 0;

while ($i < 100) {
    // ... a bunch of other code...

    libxml_use_internal_errors(true);
    $old_libxml_disable_entity_loader = libxml_disable_entity_loader(false);        $result = $DD -> schemaValidate(__DIR__ . '/schema.xsd');
    libxml_disable_entity_loader($old_libxml_disable_entity_loader); // Se desactiva nuevamente carga de entidades para descartar entidades maliciosas
    $i++;
    echo str_pad($i, 5) . ($result ? 'true' : 'false') . '<br>';

    // ... a bunch of other code...
}
  • 写回答

1条回答 默认 最新

  • dragon88112 2015-09-11 18:02
    关注

    The problem is that the whole script is reaching the 30 seconds mark, not a DOMDocument::schemaValidate() execution alone.

    The execution time corresponds to the full script executing, with all its includes and iterations in case it has.

    Consider the execution time does not count any time spent outside the script, such as in stream operations, database queries, amongst others. So for example the script may look as taking 1 minut when in reality it is taking only 15 or 30. See http://php.net/manual/en/function.set-time-limit.php which states:

    Note: The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. This is not true on Windows where the measured time is real.

    It is not ::schemaValidate() which is taking 30 seconds to execute, it is the full script. Then why once the script reach 30 seconds the error falls just inside schemaValidate()? Because altought ::schemaValidate() it is a relatively fast method to execute, it must be the most complex code inside the iteration, hence the biggest chance is the error falls when schemaValidate is executing, after N repetitions (in the real case N must be a lot).

    So the answer is ::schemaValidate() is consuming most of the execution time, hence the error ocurs virtualy always when ::schemaValidate() is executing.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥50 swiftui @query 报错
  • ¥50 怎么解决刷卡或扫码后,点击软件输入框,win10屏幕键盘不会自动弹出的问题
  • ¥15 如何使用arcgispro的训练深度模型,发现water和nowater精度为0?(相关搜索:深度学习)
  • ¥20 matlab作业不太懂呀有问题能给个代码吗
  • ¥15 自制电路图为何无法驱动ESP01S?
  • ¥15 前端加access数据库
  • ¥15 ARCGIS 多值提取到点 ERROR 999999
  • ¥15 mysql异常断电, [MY-011971] [InnoDB]
  • ¥15 uni.onBluetoothDeviceFound熄屏不运行
  • ¥15 求PHDA糖尿病并发症数据集,有偿