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.

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

报告相同问题?

悬赏问题

  • ¥100 谁能在荣耀自带系统MagicOS版本下,隐藏手机桌面图标?
  • ¥15 求SC-LIWC词典!
  • ¥20 有关esp8266连接阿里云
  • ¥15 C# 调用Bartender打印机打印
  • ¥15 我这个代码哪里有问题 acm 平台上显示错误 90%,我自己运行好像没什么问题
  • ¥50 C#编程中使用printDocument类实现文字排版打印问题
  • ¥15 找会编程的帅哥美女 可以用MATLAB里面的simulink编程,用Keil5编也可以。
  • ¥15 已知隐函数其中一个变量τ的具体值,求另一个变量
  • ¥15 r语言Hurst指数
  • ¥15 RT-Thread Studio编译问题