2017-07-12 17 views
1

XMLファイルを検証するために、XSDファイルの階層を使用しています。その中にはdtdファイルが含まれています。私は、検証フラグProcessInlineSchemaProcessSchemaLocationを設定することによって、XMLファイルのschemaLocationで参照されるスキーマに基づいてそれを成功裏に実行することができました。C#でDTD宣言を含むXSDスキーマを使用してXMLを検証する

私のシナリオでは、構築しているアプリケーションでXSDファイルを配信する必要があるため、schemaLocationを無視する必要があります(Web上のどこかを指すようになります)。 XMLファイルは標準です。

は、私は私の問題をテストするために簡単な例を作成した - 私は、次のファイルがあります。

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE xs:schema [ 
    <!ENTITY % inc.dtd SYSTEM "inc.dtd"> 
    %inc.dtd; 
]> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="ro:sopa:inc"> 
    <xs:simpleType name="testInc"> 
     <xs:restriction base="xs:string"> 
      <xs:pattern value="&test;"/> 
     </xs:restriction> 
    </xs:simpleType> 
</xs:schema> 

をinc.dtd included.xsd

<?xml version="1.0" encoding="UTF-8"?> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="ro:sopa:main" xmlns:main="ro:sopa:main" xmlns:inc="ro:sopa:inc" > 
    <xs:import namespace="ro:sopa:inc" schemaLocation="included.xsd"/> 
    <xs:element name="test" type="main:testType"/> 
    <xs:complexType name="testType"> 
     <xs:sequence> 
      <xs:element name="test1" type="inc:testInc" minOccurs="0" maxOccurs="unbounded"/> 
     </xs:sequence> 
    </xs:complexType> 
</xs:schema> 

main.xsdを

<!ENTITY digit "[0-9]{1}"> 
<!ENTITY alnum "[A-Z]{1}"> 
<!ENTITY test "&alnum;-&digit;"> 

サンプルXMLファイルは:

<main:test xsi:schemaLocation="ro:sopa:main D:\schemas\main.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:main="ro:sopa:main"> 
<test1>A-4</test1> 
</main:test> 

私が直接XMLファイルで指さスキーマに対して検証する場合は、それが正常に動作します:

List<string> report = new List<string>(); 
XmlReaderSettings settings = new XmlReaderSettings(); 
settings.ValidationType = ValidationType.Schema; 
settings.DtdProcessing = DtdProcessing.Parse; 
settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings; 
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessInlineSchema; 
settings.ValidationFlags |= XmlSchemaValidationFlags.ProcessSchemaLocation; 
settings.ValidationEventHandler += new ValidationEventHandler(delegate(object snd, ValidationEventArgs e2) 
{ 
    report.Add(e2.Message); 
}); 

XmlReader reader = XmlReader.Create(fileName, settings); 

while (reader.Read()); 

reader.Close(); 

をしかし、私は手動でXmlSchemaSetを設定しようとする場合、それは動作しません。

public static string schemaUrl = @"D:\schema\main.xsd"; 
public static string fileName = @"D:\somewhere\testProd1.xml"; 

public static void Main(string[] args) 
{ 
    List<string> report = new List<string>(); 
    XmlReaderSettings settings = new XmlReaderSettings(); 
    settings.ValidationType = ValidationType.Schema; 
    settings.DtdProcessing = DtdProcessing.Parse; 
    settings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings; 
    settings.Schemas = ProvideSchemaSet(report); 
    settings.ValidationEventHandler += new ValidationEventHandler(delegate(object snd, ValidationEventArgs e2) 
    { 
     report.Add(e2.Message); 
    }); 

    XmlReader reader = XmlReader.Create(fileName, settings); 
    while (reader.Read()) ; 
    reader.Close(); 
} 

public static XmlSchemaSet ProvideSchemaSet(List<string> schemaLoadErrors) 
{ 
    XmlSchemaSet schemas = new XmlSchemaSet(); 

    XmlReaderSettings settings = new XmlReaderSettings(); 
    settings.DtdProcessing = DtdProcessing.Parse; 
    XmlReader schemaReader = XmlReader.Create(schemaUrl, settings); 

    XmlSchema schema = XmlSchema.Read(schemaReader, delegate(object sender, ValidationEventArgs e) 
    { 
     schemaLoadErrors.Add(e.Message); 
    }); 

    schemas.Add(schema); 
    schemaReader.Close(); 

    schemas.Compile(); 
    return schemas; 
} 

これは、オブジェクトtest1が存在しないことを示すschemas.Compile()でクラッシュします。これは、私がdtdを使用する場合にのみ発生します。私がDTDをスキーマから取り出しても正しく動作します。

私がインターネットで検索したのは、具体的にはXSD検証またはDTD検証に関するものでしたが、これについての解決策は見つかりませんでした。助言がありますか?

注:私が扱う必要があるスキーマとDTDは標準化されているため、決して変更することはできません。

答えて

0

あなたは再読み込みXSDことができ、これはあなたにこの

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE xs:schema[ 
    <!ENTITY % inc.dtd SYSTEM "inc.dtd">%inc.dtd; 
]> 
<!-- Created with Liquid Studio 2018 BETA - Developer Bundle (Educational) 16.0.0.7863 (https://www.liquid-technologies.com) --> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="ro:sopa:inc"> 
    <xs:simpleType name="testInc"> 
     <xs:restriction base="xs:string"> 
      <xs:pattern value="[A-Z]{1}-[0-9]{1}" /> 
     </xs:restriction> 
    </xs:simpleType> 
</xs:schema> 

ようなXML文書を与えるだろう

 XmlReaderSettings xrs = new XmlReaderSettings(); 
     xrs.DtdProcessing = DtdProcessing.Parse; 
     xrs.IgnoreProcessingInstructions = false; 
     xrs.XmlResolver = new XmlUrlResolver(); 
     XmlReader reader = XmlReader.Create(@"c:\temp\xsd\included.xsd", xrs); 

     XmlDocument xmldoc = new XmlDocument(); 
     xmldoc.Load(reader); 
     Debug.WriteLine(xmldoc.OuterXml); 

あなたはその後、DOCTYPEを削除することができ、それを削除し、その後DTD部分を処理(おそらくXSDコンパイルを駄目にするでしょう)

 foreach (var xmlDocType in xmldoc.ChildNodes.OfType<XmlDocumentType>().ToArray()) 
      xmldoc.RemoveChild(xmlDocType); 

     Debug.WriteLine(xmldoc.OuterXml); 

このままあなたに残して

<?xml version="1.0" encoding="UTF-8"?> 
<!-- Created with Liquid Studio 2018 BETA - Developer Bundle (Educational) 16.0.0.7863 (https://www.liquid-technologies.com) --> 
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" targetNamespace="ro:sopa:inc"> 
    <xs:simpleType name="testInc"> 
     <xs:restriction base="xs:string"> 
      <xs:pattern value="[A-Z]{1}-[0-9]{1}" /> 
     </xs:restriction> 
    </xs:simpleType> 
</xs:schema> 

私はその悪いアイデアだと思いXSDにDTDを埋め込むことが法的ものの、それは本当にバリデータとツールの多くをスローします。

関連する問題