1

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

  1. “兄弟节点和祖先兄弟节点不可访问”。
  2. “您只能访问一次子节点”
  3. “您只能访问当前元素属性和命名空间声明”

我怎样才能克服这些限制?谁能帮帮我吗?

<?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>
4

1 回答 1

0

I think you should follow the approach in http://saxonica.com/documentation/index.html#!sourcedocs/streaming/burst-mode-streaming so along the lines of

<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>

That should show the approach, you will have to add code for the remaining elements like middle name and prefix and so on. I have also tried to simplify the compuation of the attribute value in some cases, I think the same can be done for the other cases but I think you should ask that in a different question where you provide details of the XML structure and the values you want to compute, all those nested for-eachs to generate a single value attribute seem a bit convoluted.

Also note that I have followed your posted code in creating a single Patient element, I would however expected that a ns0:ORM_O01.PATIENT element is mapped to a Patient so more along the lines of

<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>
于 2014-06-24T13:04:21.413 回答