XSL从2.0转换

时间:2014-06-24 05:45:47

标签: xslt xslt-3.0

我在将XSLT 2.0转换为XSLT 3.0时遇到问题。我想使用XSLT 3.0的流功能。我正在努力使用<xsl:stream><xsl:mode>标签,因为XSLT 3.0有几个限制。对于使用XSLT 3.0流功能,面临以下限制:

  1. “无法访问兄弟节点和祖先兄弟节点”。
  2. “您只能访问子节点一次”
  3. “您只能访问当前元素属性和名称空间声明”
  4. 我如何克服这些限制?有人可以帮帮我吗?

    <?xml version="1.0" encoding="UTF-8">
    
             <xsl:stream href="SampleInput3_0.xml">
                <xsl:for-each select="copy-of(ns0:ORM_O01/ns0:ORM_O01.PATIENT/ns0:PID)">
                   <Patient>
                      <ucfd:Name>
                         <xsl:variable name="varFirst_Name" as="node()" select="ns0:PID.5/ns0:XPN.2[not((translate(string(@xsi:nil), 'true ', '1') = '1'))]" />
                         <xsl:variable name="varLast_Name" as="node()" select="ns0:XPN.1/ns0:FN.1[not((translate(string(@xsi:nil), 'true ', '1') = '1'))]" />
                         <xsl:attribute name="value" namespace="" select="concat(string($varFirst_Name), string(varLast_Name))" />
                      </ucfd:Name>
                      <ucfd:FirstName value="{ns0:PID.5/ns0:XPN.2[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                      <ucfd:LastName value="{ns0:PID.5/ns0:XPN.1/ns0:FN.1}" />
                      <ucfd:MiddleName value="{ns0:PID.5/ns0:XPN.3[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                      <ucfd:Prefix value="{ns0:PID.5/ns0:XPN.5[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                      <ucfd:Suffix value="{ns0:PID.5/ns0:XPN.4[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                      <ucfd:Identification>
                         <ucfd:TaxIdentifier>
                            <ucfd:Type value="{ns0:PID.18/ns0:CX.5[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                            <ucfd:Identifier value="{ns0:PID.18/ns0:CX.1}" />
                         </ucfd:TaxIdentifier>
                      </ucfd:Identification>
                      <xsl:for-each select="ns0:PID.11">
                         <ucfd:Address>
                            <xsl:if test="exists(@Type)">
                               <ucfd:Type value="{ns0:XAD.7[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                            </xsl:if>
                            <ucfd:City value="{ns0:XAD.3[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                            <ucfd:State value="{ns0:XAD.4[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                            <ucfd:PostalCode value="{ns0:XAD.5[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                            <ucfd:Country value="{ns0:XAD.6[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                            <ucfd:County value="{ns0:XAD.9[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                         </ucfd:Address>
                      </xsl:for-each>
                      <ucfd:Contact>
                         <ucfd:Role value="{ns0:PID.13/ns0:XTN.2[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                         <ucfd:Type value="{ns0:PID.13/ns0:XTN.3[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                         <xsl:for-each select="ns0:PID.13">
                            <!--<xsl:variable name="var9_current" as="node()" select="."/>-->
                            <ucfd:CommunicationNumber>
                               <xsl:if test="exists(@Type)">
                                  <ucfd:Type>
                                     <xsl:sequence select="()" />
                                  </ucfd:Type>
                               </xsl:if>
                               <ucfd:Identifier>
                                  <!--<xsl:variable name="var8_current" as="node()" select="ns0:XTN.5[not((translate(string(@xsi:nil), 'true ', '1') = '1'))]"/>
                                    <xsl:variable name="var7_current" as="node()" select="ns0:XTN.6[not((translate(string(@xsi:nil), 'true ', '1') = '1'))]"/>
                                    <xsl:variable name="var6_current" as="node()" select="ns0:XTN.7[not((translate(string(@xsi:nil), 'true ', '1') = '1'))]"/>
                                    <xsl:variable name="var5_current" as="node()" select="ns0:XTN.8[not((translate(string(@xsi:nil), 'true ', '1') = '1'))]"/>
                                    <xsl:variable name="var4_current" as="node()" select="ns0:XTN.10[not((translate(string(@xsi:nil), 'true ', '1') = '1'))]"/>
                                    <xsl:variable name="var3_current" as="node()" select="ns0:XTN.11[not((translate(string(@xsi:nil), 'true ', '1') = '1'))]"/>
                                    <xsl:attribute name="value" namespace="" select="concat(concat(concat(concat(concat(string($var8_current), string($var7_current)), string($var6_current)), string($var5_current)), string($var4_current)), string($var3_current))"/> -->
                               </ucfd:Identifier>
                            </ucfd:CommunicationNumber>
                         </xsl:for-each>
                      </ucfd:Contact>
                      <ucfd:Demographics>
                         <ucfd:BirthDate>
                            <xsl:sequence select="()" />
                         </ucfd:BirthDate>
                         <ucfd:BirthSequenceNumber>
                            <xsl:for-each select="ns0:ORM_O01/ns0:ORM_O01.PATIENT/ns0:PID/ns0:PID.25">
                               <xsl:attribute name="value" namespace="">
                                  <xsl:if test="not((translate(string(@xsi:nil), 'true ', '1') = '1'))">
                                     <xsl:sequence select="xs:string(xs:integer(string(.)))" />
                                  </xsl:if>
                               </xsl:attribute>
                            </xsl:for-each>
                         </ucfd:BirthSequenceNumber>
                         <ucfd:DeathDate>
                            <xsl:sequence select="()" />
                         </ucfd:DeathDate>
                         <ucfd:Gender value="ns0:PID.8[not((translate(string(@xsi:nil), 'true ', '1') = '1'))]" />
                         <ucfd:MaritalStatus value="{ns0:PID.16/ns0:CE_0002.1[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                         <ucfd:CitizenshipStatus value="{ns0:PID.26[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                         <ucfd:RaceOrEthnicity>
                            <ucfd:Race value="{ns0:PID.10/ns0:CE_0005.1[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                         </ucfd:RaceOrEthnicity>
                         <ucfd:Religion value="{ns0:PID.17/ns0:CE_0006.2[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                      </ucfd:Demographics>
                      <ucfd:Language>
                         <ucfd:LanguageCode value="{ns0:PID.15/ns0:CE_0296.1[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                         <ucfd:Description value="{ns0:PID.15/ns0:CE_0296.2[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                         <ucfd:UseIndicator value="{ns0:PID.15/ns0:CE_0296.3[not(translate(@xsi:nil, 'true ', '1') = '1')]}" />
                      </ucfd:Language>
                   </Patient>
                </xsl:for-each>
             </xsl:stream>
          </MemberRecord>
       </xsl:template>
    </xsl:stylesheet>
    

1 个答案:

答案 0 :(得分:0)

我认为你应该遵循http://saxonica.com/documentation/index.html#!sourcedocs/streaming/burst-mode-streaming中的方法,以便按照

的方式进行
<xsl:stylesheet 
  version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ns0="..."
  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="..." xmlns:ccfd="..." xmlns:hcfd="..." xmlns:ucf="..." xmlns:ucfd="..."
  exclude-result-prefixes="ns0 xs">

<xsl:output method="xml" encoding="UTF-8" byte-order-mark="no" indent="yes"/>

<!-- start with this named template -->
<xsl:template name="main">
  <MemberRecord xsi:schemaLocation="...">
    <Patient>
      <xsl:stream href='employees.xml'>
        <xsl:apply-templates select="copy-of(ns0:ORM_O01/ns0:ORM_O01.PATIENT/ns0:PID)"/>
      </xsl:stream>
    </Patient>
  </MemberRecord>
</xsl:template>

<xsl:template match="ns0:PID">
  <ucfd:Name value="{...}"/>
  <ucfd:FirstName value="{ns0:PID.5/ns0:XPN.2[not(translate(@xsi:nil, 'true ', '1') = '1'))]}"/>
  <ucfd:LastName value="{ns0:PID.5/ns0:XPN.1/ns0:FN.1}"/>
  <!-- compute the other elements and attributes here as above -->
</xsl:template>

</xsl:stylesheet>

这应该显示方法,你将不得不为其他元素添加代码,如中间名和前缀等。在某些情况下,我也尝试简化属性value的编译,我认为对其他情况也可以这样做但我认为你应该在另一个问题中提出,你提供XML结构的细节和你想要计算的值,所有那些嵌套for-eachs以生成单个value属性似乎有点复杂。

另请注意,我在创建单个Patient元素时已按照您发布的代码进行操作,但我希望将ns0:ORM_O01.PATIENT元素映射到Patient,以便更多

<xsl:stylesheet 
  version="3.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:ns0="..."
  xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="..." xmlns:ccfd="..." xmlns:hcfd="..." xmlns:ucf="..." xmlns:ucfd="..."
  exclude-result-prefixes="ns0 xs">

<xsl:output method="xml" encoding="UTF-8" byte-order-mark="no" indent="yes"/>

<!-- start with this named template -->
<xsl:template name="main">
  <MemberRecord xsi:schemaLocation="...">

      <xsl:stream href='employees.xml'>
        <xsl:apply-templates select="copy-of(ns0:ORM_O01/ns0:ORM_O01.PATIENT)"/>
      </xsl:stream>
    </Patient>
  </MemberRecord>
</xsl:template>

<xsl:template match="ns0:ORM_O01.PATIENT">
  <Patient>
    <xsl:apply-templates/>
  </Patient>
</xsl:template>

<xsl:template match="ns0:PID">
  <ucfd:Name value="{...}"/>
  <ucfd:FirstName value="{ns0:PID.5/ns0:XPN.2[not(translate(@xsi:nil, 'true ', '1') = '1'))]}"/>
  <ucfd:LastName value="{ns0:PID.5/ns0:XPN.1/ns0:FN.1}"/>
  <!-- compute the other elements and attributes here as above -->
</xsl:template>

</xsl:stylesheet>