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.

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

报告相同问题?

悬赏问题

  • ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line
  • ¥500 火焰左右视图、视差(基于双目相机)