关于Saxon XsltTransformer Class的问题是;
我正在测试Saxon .NET示例并根据上一个WriteLine()方法的输出,下面的示例代码应该将验证/转换结果打印到文件(outfile),但始终将结果重定向到stdout并且文件始终为空。< / p>
我的问题所以问题是如何将Xslt验证/转换结果作为字符串,MemoryStream等 ... ...我的主要目的,使这些事务(XsltTransformer.Run()和其他要求内存中的事务和获取结果)(不在磁盘上创建任何文件)。
我会尝试与memorystream进行相同的事务以获得结果为字符串(没有磁盘上的文件)但我没有得到结果作为文件。我在这里......
.NET版本:4.5
Saxon API版本:SaxonHE9.5N
感谢您的回答并抱歉我的英语。
Uri schemaUri = new Uri(@"file:\\C:\path\to\my.xml");
Uri xslUri = new Uri(@"file:\\C:\path\to\my.xsl");
// Create a Processor instance.
Processor processor = new Processor();
// Load the source document
XdmNode input = processor.NewDocumentBuilder().Build(schemaUri);
// Create a transformer for the stylesheet.
XsltTransformer transformer = processor.NewXsltCompiler().Compile(xslUri).Load();
// Set the root node of the source document to be the initial context node
transformer.InitialContextNode = input;
// Create a serializer
String outfile = "OutputFromXsltSimple2.xml";
Serializer serializer = new Serializer();
FileStream fs = new FileStream(outfile, FileMode.Create, FileAccess.Write);
serializer.SetOutputStream(fs);
// Transform the source XML to System.out.
transformer.Run(serializer);
//fs.Flush();
//fs.Close();
Console.WriteLine("\nOutput written to " + outfile + "\n");
更新 在Java方面,我正在使用此代码块执行此操作;
TransformerFactory tfactory = TransformerFactory.newInstance();
Transformer transformer = tfactory.newTransformer(new StreamSource("/path/to/my.xsl"));
StreamResult sr = new StreamResult();
StringWriter sw = new StringWriter();
sr.setSystemId("DENEMME");
transformer.transform(new StreamSource("/path/to/my.xml"), sr);
System.out.println("----------------");
System.out.println(sw.getBuffer().toString());
在XSL中,有XML节点值或属性值的数据验证。如果根据XSL存在任何无效值,则在StreamResult中收集所有错误消息。
我也在使用Saxon XSLT API for Java和.NET。但是当我在.NET端执行Java示例时,示例App抛出异常;
提供商 com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl 没找到。
所以我正在为C#尝试第一个示例代码片段。
更新2(架构师验证所需的XML文件):
规则XML
存储抽象规则的模式
<!-- Rule to validate StandardBusinessDocument -->
<sch:rule abstract="true" id="DocumentCheck">
<sch:assert test="sh:StandardBusinessDocumentHeader">sh:StandardBusinessDocumentHeader zorunlu bir elemandır.</sch:assert>
<sch:assert test="ef:Package">ef:Package zorunlu bir elemandır.</sch:assert>
</sch:rule>
<!-- Rules to validate StandardBusinessDocumentHeader -->
<sch:rule abstract="true" id="HeaderCheck">
<sch:assert test="sh:HeaderVersion = '1.0'">Geçersiz sh:HeaderVersion elemanı değeri. sh:HeaderVersion elemanı '1.0' değerine eşit olmalıdır.</sch:assert>
<sch:assert test="count(sh:Sender) = 1">sh:Sender zorunlu bir elemandır.</sch:assert>
<sch:assert test="count(sh:Receiver) = 1">sh:Receiver zorunlu bir elemandır.</sch:assert>
</sch:rule>
<!-- Rule to validate given value empty or not -->
<sch:rule abstract="true" id="EmptyCheck">
<sch:assert test="string-length(normalize-space(string(.))) != 0">Geçersiz <sch:name/> elemanı değeri. Boş olmayan bir değer içermelidir.</sch:assert>
</sch:rule>
<!-- Rule to validate ContactInformation -->
<sch:rule abstract="true" id="ContactInformationCheck">
<sch:assert test="count(sh:ContactInformation) > 0">En az bir sh:ContactInformation elemanı bulunmalıdır.</sch:assert>
<sch:assert test="count(sh:ContactInformation[sh:ContactTypeIdentifier = 'VKN_TCKN']) = 1 ">sh:ContactTypeIdentifier elemanı değeri 'VKN_TCKN' ye eşit olan bir tane sh:ContactInformation elemanı bulunmalıdır.</sch:assert>
</sch:rule>
<!-- Rule to validate Contact -->
<sch:rule abstract="true" id="ContactCheck">
<sch:assert test="sh:ContactTypeIdentifier">sh:ContactTypeIdentifier zorunlu bir elemandır.</sch:assert>
<sch:assert test="not(sh:ContactTypeIdentifier) or contains($ContactTypeIdentifierType, concat(',',sh:ContactTypeIdentifier,','))">Geçersiz sh:ContactTypeIdentifier değeri : '<sch:value-of select="sh:ContactTypeIdentifier"/>'. Geçerli değerler için kod listesine bakınız.</sch:assert>
<sch:assert test="not(sh:ContactTypeIdentifier) or not(sh:ContactTypeIdentifier = 'VKN_TCKN') or string-length(sh:Contact) = 11 or string-length(sh:Contact) = 10">sh:ContactTypeIdentifier elemanın değeri 'VKN_TCKN' olması durumunda sh:Contact elemanına 10 haneli vergi kimlik numarası ve ya 11 haneli TC kimlik numarası yazılmalıdır.</sch:assert>
</sch:rule>
<!-- Rule to validate DocumentIdentification.TypeVersion -->
<sch:rule abstract="true" id="TypeVersionCheck">
<sch:assert test="sh:TypeVersion = '1.0'">Geçersiz sh:TypeVersion elemanı değeri. sh:TypeVersion '1.0' değerine eşit olmalıdır.</sch:assert>
</sch:rule>
<!-- Rule to validate DocumentIdentification.Type -->
<sch:rule abstract="true" id="EnvelopeTypeCheck">
<sch:assert test="contains($EnvelopeType, concat(',',sh:Type,','))">Geçersiz zarf türü : '<sch:value-of select="sh:Type"/>'. Geçerli değerler için kod listesine bakınız.</sch:assert>
</sch:rule>
<!-- Rule to validate EnvelopeType with given ElementType-->
<sch:rule abstract="true" id="EnvelopeTypeElementTypeCheck">
<sch:assert test="not(sh:Type = 'SENDERENVELOPE') or not(//ElementType != 'INVOICE')">SENDERENVELOPE türündeki zarf Invoice şemasında göre oluşturulmuş belge taşımalıdır.</sch:assert>
<sch:assert test="not(sh:Type = 'POSTBOXENVELOPE') or not(//ElementType != 'APPLICATIONRESPONSE')">POSTBOXENVELOPE türündeki zarf ApplicationResponse şemasında göre oluşturulmuş belge taşımalıdır.</sch:assert>
<sch:assert test="not(sh:Type = 'SYSTEMENVELOPE') or not(//ElementType != 'APPLICATIONRESPONSE')">SYSTEMENVELOPE türündeki zarf ApplicationResponse şemasına göre oluşturulmuş belge taşımalıdır.</sch:assert>
<sch:assert test="not(sh:Type = 'USERENVELOPE') or (//ElementType = 'PROCESSUSERACCOUNT' or //ElementType = 'CANCELUSERACCOUNT')">USERENVELOPE türündeki zarf ProcessUserAccount ve ya CancelUserAccount şemasına göre oluşturulmuş belge taşımalıdır.</sch:assert>
<sch:assert test="not(sh:Type = 'USERENVELOPE') or ($receiverId = '3900383669' and $receiverAlias = 'GIB')">USERENVELOPE türündeki zarfı yalnızca 3900383669 vergi kimlik numaralı ve GIB etiketli kullanıcıya gönderebilirsiniz.</sch:assert>
<sch:assert test="not(sh:Type = 'USERENVELOPE') or ($senderAlias = 'usergb')">USERENVELOPE türündeki zarfı yalnızca 'usergb' etiketine sahip kullanıcı gönderebilir.</sch:assert>
</sch:rule>
<!-- Rules to validate Package -->
<sch:rule abstract="true" id="ElementsGroupCountCheck">
<sch:assert test="count(Elements) < 11">ef:Package elemanı içerisinde en fazla 10 tane Elements elemanı olabilir.</sch:assert>
</sch:rule>
<sch:rule abstract="true" id="ElementTypeCheck">
<sch:assert test="contains($ElementType, concat(',',ElementType,','))">Geçersiz ElementType değeri : '<sch:value-of select="ElementType"/>'. Geçerli ElementType değerleri için kod listesine bakınız.</sch:assert>
</sch:rule>
<sch:rule abstract="true" id="ElementCountCheck">
<sch:assert test="ElementCount < 1001">ElementCount elemanın değeri en fazla 1000 olabilir..</sch:assert>
</sch:rule>
<sch:rule abstract="true" id="ElementListCountCheck">
<sch:assert test="count(ElementList/*) = ElementCount ">ElementList elemanı içersinde bulunan eleman sayısı ElementCount elemanı değerine eşit olmalıdır.</sch:assert>
</sch:rule>...
主要验证XML(使用上下文执行规则)
<?xml version="1.0" encoding="UTF-8"?>
<sch:schema xmlns="http://purl.oclc.org/dsdl/schematron"
xmlns:sch="http://purl.oclc.org/dsdl/schematron"
xmlns:sh="http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader"
xmlns:ef="http://www.efatura.gov.tr/envelope-namespace">
<sch:include href="UBL-TR_Codelist.xml#codes"/>
<sch:include href="UBL-TR_Common_Schematron.xml#abstracts"/>
<sch:ns prefix="sh" uri="http://www.unece.org/cefact/namespaces/StandardBusinessDocumentHeader" />
<sch:ns prefix="ef" uri="http://www.efatura.gov.tr/package-namespace" />
<sch:ns prefix="inv" uri="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" />
<sch:ns prefix="apr" uri="urn:oasis:names:specification:ubl:schema:xsd:ApplicationResponse-2" />
<sch:ns prefix="cac" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" />
<sch:ns prefix="cbc" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2" />
<sch:ns prefix="ext" uri="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2" />
<sch:ns prefix="ds" uri="http://www.w3.org/2000/09/xmldsig#" />
<sch:ns prefix="xades" uri="http://uri.etsi.org/01903/v1.3.2#" />
<sch:ns prefix="hr" uri="http://www.hr-xml.org/3" />
<sch:ns prefix="oa" uri="http://www.openapplications.org/oagis/9" />
<let name="envelopeType" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:DocumentIdentification/sh:Type"/>
<let name="senderId" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Sender/sh:ContactInformation[sh:ContactTypeIdentifier = 'VKN_TCKN']/sh:Contact"/>
<let name="senderAlias" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Sender/sh:Identifier"/>
<let name="receiverId" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Receiver/sh:ContactInformation[sh:ContactTypeIdentifier = 'VKN_TCKN']/sh:Contact"/>
<let name="receiverAlias" value="/sh:StandardBusinessDocument/sh:StandardBusinessDocumentHeader/sh:Receiver/sh:Identifier"/>
<let name="responseCode" value="//apr:ApplicationResponse/cac:DocumentResponse/cac:Response/cbc:ResponseCode" />
<!-- StandardBusinessDocument -->
<sch:pattern id="document">
<sch:rule context="sh:StandardBusinessDocument">
<sch:extends rule="DocumentCheck"/>
</sch:rule>
</sch:pattern>
<!-- StandardBusinessDocumentHeader -->
<sch:pattern id="header">
<sch:rule context="sh:StandardBusinessDocumentHeader">
<sch:extends rule="HeaderCheck"/>
</sch:rule>
<sch:rule context="sh:StandardBusinessDocumentHeader/sh:Sender/sh:Identifier">
<sch:extends rule="EmptyCheck"/>
</sch:rule>
<sch:rule context="sh:StandardBusinessDocumentHeader/sh:Receiver/sh:Identifier">
<sch:extends rule="EmptyCheck"/>
</sch:rule>
<sch:rule context="sh:StandardBusinessDocumentHeader/sh:Sender">
<sch:extends rule="ContactInformationCheck"/>
</sch:rule>
<sch:rule context="sh:StandardBusinessDocumentHeader/sh:Receiver">
<sch:extends rule="ContactInformationCheck"/>
</sch:rule>
<sch:rule context="sh:StandardBusinessDocumentHeader/sh:Sender/sh:ContactInformation">
<sch:extends rule="ContactCheck"/>
</sch:rule>
...
代码列表XML
<sch:schema xmlns="http://purl.oclc.org/dsdl/schematron"
xmlns:sch="http://purl.oclc.org/dsdl/schematron">
<sch:pattern name="CodeList" id="codes">
<sch:let name="ProfileIDType" value="',TICARIFATURA,TEMELFATURA,'"/>
<sch:let name="InvoiceTypeCodeList" value="',SATIS,IADE,'"/>
<sch:let name="EnvelopeType" value="',SENDERENVELOPE,POSTBOXENVELOPE,SYSTEMENVELOPE,USERENVELOPE,'"/>
<sch:let name="ElementType" value="',INVOICE,APPLICATIONRESPONSE,PROCESSUSERACCOUNT,CANCELUSERACCOUNT,'"/>
<sch:let name="TaxType" value="',0003,0015,0061,0071,0073,0074,0075,0076,0077,1047,1048,4080,4081,9015,9021,9077,8001,8002,8003,8004,8005,8006,8007,8008,'"/>
<sch:let name="PartyIdentificationIDType" value="',TCKN,VKN,HIZMETNO,MUSTERINO,TESISATNO,TELEFONNO,DISTRIBUTORNO,TICARETSICILNO,TAPDKNO,BAYINO,ABONENO,SAYACNO,'"/>
<sch:let name="ResponseCodeType" value="',KABUL,RED,IADE,S_APR,'"/>
<sch:let name="ContactTypeIdentifierType" value="',UNVAN,VKN_TCKN,'"/>
<sch:let name="CurrencyCodeList" value="',AED,AFN,ALL,AMD,ANG,AOA,ARS,AUD,AWG,AZM,BAM,BBD,BDT,BGN,BHD,BIF,BMD,BND,BOB,BRL,BSD,BTN,BWP,BYR,BZD,CAD,CDF,CHF,CLP,CNY,COP,CRC,CUP,CVE,CYP,CZK,DJF,DKK,DOP,DZD,EEK,EGP,ERN,ETB,EUR,FJD,FKP,GBP,GEL,GHC,GIP,GMD,GNF,GTQ,GYD,HKD,HNL,HRK,HTG,HUF,IDR,ILS,INR,IQD,IRR,ISK,JMD,JOD,JPY,KES,KGS,KHR,KMF,KPW,KRW,KWD,KYD,KZT,LAK,LBP,LKR,LRD,LSL,LTL,LVL,LYD,MAD,MDL,MGF,MKD,MMK,MNT,MOP,MRO,MTL,MUR,MVR,MWK,MXN,MYR,MZM,NAD,NGN,NIO,NOK,NPR,NZD,OMR,PAB,PEN,PGK,PHP,PKR,PLN,PYG,QAR,ROL,RUB,RWF,SAR,SBD,SCR,SDD,SEK,SGD,SHP,SIT,SKK,SLL,SOS,SRG,STD,SVC,SYP,SZL,THB,TJS,TMM,TND,TOP,TRL,TTD,TWD,TZS,UAH,UGX,USD,UYU,UZS,VEB,VND,VUV,WST,XAF,XAG,XAU,XCD,XDR,XOF,XPD,XPF,XPT,YER,YUM,ZAR,ZMK,ZWD,'"/>
<sch:let name="CountryCodeList" value="',AF,AX,AL,DZ,AS,AD,AO,AI,AQ,AG,AR,AM,AW,AU,AT,AZ,BS,BH,BD,BB,BY,BE,BZ,BJ,BM,BT,BO,BA,BW,BV,BR,IO,BN,BG,BF,BI,KH,CM,CA,CV,KY,CF,TD,CL,CN,CX,CC,CO,KM,CG,CD,CK,CR,CI,HR,CU,CY,CZ,DK,DJ,DM,DO,EC,EG,SV,GQ,ER,EE,ET,FK,FO,FJ,FI,FR,GF,PF,TF,GA,GM,GE,DE,GH,GI,GR,GL,GD,GP,GU,GT,GG,GN,GW,GY,HT,HM,VA,HN,HK,HU,IS,IN,ID,IR,IQ,IE,IM,IL,IT,JM,JP,JE,JO,KZ,KE,KI,KP,KR,KW,KG,LA,LV,LB,LS,LR,LY,LI,LT,LU,MO,MK,MG,MW,MY,MV,ML,MT,MH,MQ,MR,MU,YT,MX,FM,MD,MC,MN,ME,MS,MA,MZ,MM,NA,NR,NP,NL,AN,NC,NZ,NI,NE,NG,NU,NF,MP,NO,OM,PK,PW,PS,PA,PG,PY,PE,PH,PN,PL,PT,PR,QA,RE,RO,RU,RW,BL,SH,KN,LC,MF,PM,VC,WS,SM,ST,SA,SN,RS,SC,SL,SG,SK,SI,SB,SO,ZA,GS,ES,LK,SD,SR,SJ,SZ,SE,CH,SY,TW,TJ,TZ,TH,TL,TG,TK,TO,TT,TN,TR,TM,TC,TV,UG,UA,AE,GB,US,UM,UY,UZ,VU,VE,VN,VG,VI,WF,EH,YE,ZM,ZW,'"/>
<sch:let name="UserType" value="',1,2,11,12,'"/>
<sch:let name="ReservedAliases" value="',usergb,GIB,'"/>
</sch:pattern>
</sch:schema>
我无法完全共享所有文件,超出了body max character ...
对于xsl文件,我组合了这3个XML文件,并将这个组合的xml提供给Oxygen XML Editor,我使用了Oxygen Editor输出的XSL文件,用于我的组合xml。 (Oxygen Editor忽略了第二个XML的include语句,所以我手动将所有XML文件合并为一个XML文件。)
Xsl的一小部分;
<axsl:choose>
<axsl:when test="ef:Package"/>
<axsl:otherwise>
<axsl:message>ef:Package zorunlu bir elemandır.<axsl:text> (</axsl:text>ef:Package<axsl:text>)</axsl:text>
<axsl:text> [</axsl:text>assert<axsl:text>]</axsl:text>
</axsl:message>
</axsl:otherwise>
</axsl:choose>
<axsl:apply-templates select="@*|*|comment()|processing-instruction()" mode="M19"/>
</axsl:template>
<axsl:template match="text()" priority="-1" mode="M19"/>
<axsl:template match="@*|node()" priority="-2" mode="M19">
<axsl:choose><!--Housekeeping: SAXON warns if attempting to find the attribute
of an attribute-->
<axsl:when test="not(@*)">
<axsl:apply-templates select="node()" mode="M19"/>
</axsl:when>
<axsl:otherwise>
<axsl:apply-templates select="@*|node()" mode="M19"/>
</axsl:otherwise>
</axsl:choose>
</axsl:template>
<!--PATTERN header-->
<!--RULE -->
<axsl:template match="sh:StandardBusinessDocumentHeader" priority="109" mode="M20">
<!--ASSERT -->
<axsl:choose>
<axsl:when test="sh:HeaderVersion = '1.0'"/>
<axsl:otherwise>
<axsl:message>Geçersiz sh:HeaderVersion elemanı değeri. sh:HeaderVersion elemanı '1.0' değerine eşit olmalıdır.<axsl:text> (</axsl:text>sh:HeaderVersion = '1.0'<axsl:text>)</axsl:text>
<axsl:text> [</axsl:text>assert<axsl:text>]</axsl:text>
</axsl:message>
</axsl:otherwise>
</axsl:choose>
<!--ASSERT -->
<axsl:choose>
<axsl:when test="count(sh:Sender) = 1"/>
<axsl:otherwise>
<axsl:message>sh:Sender zorunlu bir elemandır.<axsl:text> (</axsl:text>count(sh:Sender) = 1<axsl:text>)</axsl:text>
<axsl:text> [</axsl:text>assert<axsl:text>]</axsl:text>
</axsl:message>
</axsl:otherwise>
</axsl:choose>
<!--ASSERT -->
<axsl:choose>
<axsl:when test="count(sh:Receiver) = 1"/>
<axsl:otherwise>
<axsl:message>sh:Receiver zorunlu bir elemandır.<axsl:text> (</axsl:text>count(sh:Receiver) = 1<axsl:text>)</axsl:text>
<axsl:text> [</axsl:text>assert<axsl:text>]</axsl:text>
</axsl:message>
</axsl:otherwise>
</axsl:choose>
<axsl:apply-templates select="@*|*|comment()|processing-instruction()" mode="M20"/>
</axsl:template>
<!--RULE -->
<axsl:template match="sh:StandardBusinessDocumentHeader/sh:Sender/sh:Identifier" priority="108" mode="M20">
<!--ASSERT -->
<axsl:choose>
<axsl:when test="string-length(normalize-space(string(.))) != 0"/>
<axsl:otherwise>
<axsl:message>Geçersiz <axsl:text/>
<axsl:value-of select="name(.)"/>
<axsl:text/> elemanı değeri. Boş olmayan bir değer içermelidir.<axsl:text> (</axsl:text>string-length(normalize-space(string(.))) != 0<axsl:text>)</axsl:text>
<axsl:text> [</axsl:text>assert<axsl:text>]</axsl:text>
</axsl:message>
</axsl:otherwise>
</axsl:choose>
<axsl:apply-templates select="@*|*|comment()|processing-instruction()" mode="M20"/>
</axsl:template>
解决了 Michael Kay 的回答
只写了这堂课:
public void Message(XdmNode content, bool terminate, IXmlLocation location) {
//System.Console.WriteLine("content: " + content.BaseUri);
System.Console.WriteLine("content: " + content.Count);
System.Console.WriteLine("content: " + content.NodeKind.ToString());
System.Console.WriteLine("content: " + content.StringValue);
System.Console.WriteLine("content: " + content.OuterXml);
System.Console.WriteLine("----------------------------------------");
System.Console.WriteLine("terminate: " + terminate);
System.Console.WriteLine("----------------------------------------");
System.Console.WriteLine("terminate: " + location.BaseUri);
System.Console.WriteLine("terminate: " + location.LineNumber);
System.Console.WriteLine("----------------------------------------");
System.Console.WriteLine("----------------------------------------");
System.Console.WriteLine("----------------------------------------");
System.Console.WriteLine("----------------------------------------");
System.Console.WriteLine("----------------------------------------");
}
试试;
MyMessageListener myMessageListener = new MyMessageListener();
transformer.MessageListener = myMessageListener;
MessageListener类可以处理验证错误消息。
答案 0 :(得分:1)
可以通过在XsltTransformer对象上设置MessageListener属性来重定向xsl:message的输出。您需要实现IMessageListener接口,该接口有一个方法Message()。消息的内容以XdmNode的形式提供;如果您的消息是一个简单的字符串(而不是结构化的XML),那么您只需使用此节点的StringValue属性来获取消息内容。
我怀疑主要结果树是空的原因是你没有写任何东西;也就是说,您唯一的输出是xsl:message输出。如果没有看到完整的样式表,我无法确认。