以字符串形式获取Saxon XsltTransformer.Run()结果

时间:2014-01-20 14:47:26

标签: c# .net xslt saxon

关于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) &gt; 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) &lt; 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 &lt; 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类可以处理验证错误消息。

1 个答案:

答案 0 :(得分:1)

可以通过在XsltTransformer对象上设置MessageListener属性来重定向xsl:message的输出。您需要实现IMessageListener接口,该接口有一个方法Message()。消息的内容以XdmNode的形式提供;如果您的消息是一个简单的字符串(而不是结构化的XML),那么您只需使用此节点的StringValue属性来获取消息内容。

我怀疑主要结果树是空的原因是你没有写任何东西;也就是说,您唯一的输出是xsl:message输出。如果没有看到完整的样式表,我无法确认。