错误 "different target namespace",但模式验证和名称空间匹配?
Error "different target namespace", but schema validates and namespaces match?
我有一个 XSD 和几个不同的 XML 消息从客户端发送到服务器,服务器试图使用模式验证消息。我正在使用 Xerces 进行解析。 XSD 和 XML 都是有效的,我 运行 通过几个工具 (for example) 来验证 XML 是否使用该模式进行了验证。
然而,当我运行这个程序时,它打印出:
Parsing Error: Schema in /path/to/xsd/MySchema.xsd has a different target namespace from the one specified in the instance document .
(该路径是架构的正确位置,因此它正在按预期读取文件。)我对名称空间了解不多,因此我尽量简化。这是 XSD 文件:
<xs:schema
xmlns="http://www.mywebsite.com/schema/myschema"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
targetNamespace="http://www.mywebsite.com/schema/myschema">
<xs:element name="My_Data">
<xs:complexType>
<xs:sequence>
<xs:element name="PartOne" type="SubType" minOccurs="0" maxOccurs="1"/>
<xs:element name="PartTwo" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="SubType">
<xs:sequence>
<xs:element name="ElemOne" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
和 XML:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<My_Data
xmlns="http://www.mywebsite.com/schema/myschema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema">
<PartOne>
<ElemOne>thing</ElemOne>
</PartOne>
<PartTwo>123</PartTwo>
</My_Data>
我已经尝试了很多变体,包括添加 schemaLocation 属性,但它总是返回到目标命名空间。如果我从上面的例子中取出 ElemOne
并且不使用 targetNamespace,它解析没有问题。为什么我会得到这个错误?这实际上是命名空间的问题(在这种情况下,为什么在线工具无法捕捉到它?),还是其他问题?
编辑:这是我用来 运行 的 C++ 代码:
// g++ -g -Wall -pedantic -L /usr/lib -o schemasend schemasend.cc CustomParserErrorHandler.cc -lxerces-c
#include <xercesc/framework/MemBufInputSource.hpp>
#include "CustomParserErrorHandler.hh"
#include <string>
#include <iostream>
int main(int argc, char* argv[])
{
xercesc::XMLPlatformUtils::Initialize();
std::cout << "Intialized" << std::endl;
try {
// Parse document
const std::string aXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?><My_Data xmlns=\"http://www.mywebsite.com/schema/myschema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema\"><PartOne><ElemOne>thing</ElemOne></PartOne><PartTwo>123</PartTwo></My_Data>";
static std::string aXSDFilePath("MySchema.xsd");
CustomParserErrorHandler aErrorHandler; // just a very basic implementation of error handling
const xercesc::MemBufInputSource aInputSource(
(const XMLByte*)aXML.c_str(),
static_cast<uint>(aXML.size()),
"stringBuffer");
xercesc::XercesDOMParser* aParser = new xercesc::XercesDOMParser();
aParser->cacheGrammarFromParse(true);
aParser->setErrorHandler(&aErrorHandler);
aParser->setDoNamespaces(true);
aParser->setDoSchema(true);
aParser->setValidationSchemaFullChecking(true);
aParser->setValidationScheme(xercesc::XercesDOMParser::Val_Always);
aParser->setExternalNoNamespaceSchemaLocation((char*)NULL);
aParser->setExternalNoNamespaceSchemaLocation(aXSDFilePath.c_str());
aParser->setDoNamespaces(true);
aParser->setDoSchema(true);
aParser->setValidationScheme(xercesc::XercesDOMParser::Val_Always);
aParser->parse(aInputSource);
xercesc::DOMDocument* aDocument = aParser->getDocument();
if (!aErrorHandler.HasErrorOccurred())
{
std::cout << "--- PARSE WORKED ---" << std::endl;
// do more things
}
else
{
std::cout <<"--- PARSE ERROR ---" << std::endl
<< aErrorHandler.GetErrorString().c_str() << std::endl
<< "--- IN XML ---" << std::endl
<< aXML.c_str() << std::endl;
/* relevant error handler code:
void CustomParserErrorHandler::HandleError(
const xercesc::SAXParseException &aException,
std::stringstream &aStream)
{
aStream
<< xercesc::XMLString::transcode(aException.getMessage())
<< " at line " << aException.getLineNumber()
<< ", char " << aException.getColumnNumber()
<< " in file "
<< xercesc::XMLString::transcode(aException.getSystemId())
<< std::endl;
}
*/
}
}
catch (const xercesc::XMLException& toCatch) {
std::cout << "ERROR" << std::endl;
return 1;
}
xercesc::XMLPlatformUtils::Terminate();
std::cout << "bye" << std::endl;
return 0;
}
问题出在我的 C++ 代码中,而不是 XML/XSD 文件中。当我注释掉行
aParser->setExternalNoNamespaceSchemaLocation(aXSDFilePath.c_str());
它不再给出错误信息。我不确定为什么这会产生影响,因为据我所知,命名空间中没有任何 not,但它解决了我看到的问题。
我有一个 XSD 和几个不同的 XML 消息从客户端发送到服务器,服务器试图使用模式验证消息。我正在使用 Xerces 进行解析。 XSD 和 XML 都是有效的,我 运行 通过几个工具 (for example) 来验证 XML 是否使用该模式进行了验证。
然而,当我运行这个程序时,它打印出:
Parsing Error: Schema in /path/to/xsd/MySchema.xsd has a different target namespace from the one specified in the instance document .
(该路径是架构的正确位置,因此它正在按预期读取文件。)我对名称空间了解不多,因此我尽量简化。这是 XSD 文件:
<xs:schema
xmlns="http://www.mywebsite.com/schema/myschema"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
targetNamespace="http://www.mywebsite.com/schema/myschema">
<xs:element name="My_Data">
<xs:complexType>
<xs:sequence>
<xs:element name="PartOne" type="SubType" minOccurs="0" maxOccurs="1"/>
<xs:element name="PartTwo" type="xs:integer" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="SubType">
<xs:sequence>
<xs:element name="ElemOne" type="xs:string" />
</xs:sequence>
</xs:complexType>
</xs:schema>
和 XML:
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<My_Data
xmlns="http://www.mywebsite.com/schema/myschema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema">
<PartOne>
<ElemOne>thing</ElemOne>
</PartOne>
<PartTwo>123</PartTwo>
</My_Data>
我已经尝试了很多变体,包括添加 schemaLocation 属性,但它总是返回到目标命名空间。如果我从上面的例子中取出 ElemOne
并且不使用 targetNamespace,它解析没有问题。为什么我会得到这个错误?这实际上是命名空间的问题(在这种情况下,为什么在线工具无法捕捉到它?),还是其他问题?
编辑:这是我用来 运行 的 C++ 代码:
// g++ -g -Wall -pedantic -L /usr/lib -o schemasend schemasend.cc CustomParserErrorHandler.cc -lxerces-c
#include <xercesc/framework/MemBufInputSource.hpp>
#include "CustomParserErrorHandler.hh"
#include <string>
#include <iostream>
int main(int argc, char* argv[])
{
xercesc::XMLPlatformUtils::Initialize();
std::cout << "Intialized" << std::endl;
try {
// Parse document
const std::string aXML = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?><My_Data xmlns=\"http://www.mywebsite.com/schema/myschema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema\"><PartOne><ElemOne>thing</ElemOne></PartOne><PartTwo>123</PartTwo></My_Data>";
static std::string aXSDFilePath("MySchema.xsd");
CustomParserErrorHandler aErrorHandler; // just a very basic implementation of error handling
const xercesc::MemBufInputSource aInputSource(
(const XMLByte*)aXML.c_str(),
static_cast<uint>(aXML.size()),
"stringBuffer");
xercesc::XercesDOMParser* aParser = new xercesc::XercesDOMParser();
aParser->cacheGrammarFromParse(true);
aParser->setErrorHandler(&aErrorHandler);
aParser->setDoNamespaces(true);
aParser->setDoSchema(true);
aParser->setValidationSchemaFullChecking(true);
aParser->setValidationScheme(xercesc::XercesDOMParser::Val_Always);
aParser->setExternalNoNamespaceSchemaLocation((char*)NULL);
aParser->setExternalNoNamespaceSchemaLocation(aXSDFilePath.c_str());
aParser->setDoNamespaces(true);
aParser->setDoSchema(true);
aParser->setValidationScheme(xercesc::XercesDOMParser::Val_Always);
aParser->parse(aInputSource);
xercesc::DOMDocument* aDocument = aParser->getDocument();
if (!aErrorHandler.HasErrorOccurred())
{
std::cout << "--- PARSE WORKED ---" << std::endl;
// do more things
}
else
{
std::cout <<"--- PARSE ERROR ---" << std::endl
<< aErrorHandler.GetErrorString().c_str() << std::endl
<< "--- IN XML ---" << std::endl
<< aXML.c_str() << std::endl;
/* relevant error handler code:
void CustomParserErrorHandler::HandleError(
const xercesc::SAXParseException &aException,
std::stringstream &aStream)
{
aStream
<< xercesc::XMLString::transcode(aException.getMessage())
<< " at line " << aException.getLineNumber()
<< ", char " << aException.getColumnNumber()
<< " in file "
<< xercesc::XMLString::transcode(aException.getSystemId())
<< std::endl;
}
*/
}
}
catch (const xercesc::XMLException& toCatch) {
std::cout << "ERROR" << std::endl;
return 1;
}
xercesc::XMLPlatformUtils::Terminate();
std::cout << "bye" << std::endl;
return 0;
}
问题出在我的 C++ 代码中,而不是 XML/XSD 文件中。当我注释掉行
aParser->setExternalNoNamespaceSchemaLocation(aXSDFilePath.c_str());
它不再给出错误信息。我不确定为什么这会产生影响,因为据我所知,命名空间中没有任何 not,但它解决了我看到的问题。