【问题标题】:XSLT Validation: using for-eachXSLT 验证:使用 for-each
【发布时间】:2014-02-23 04:31:50
【问题描述】:

首先,我要说我不是程序员。然而,不知何故,我一直忙于编写 XSLT 验证模板。我正在尽我所能用我所知道的一点点,并且已经能够从搜索网络中获得。但是,我被困在使用“for-each”构造的一个逻辑上。无论如何,如果你好心回答,请慢慢说,用小词儿!

我正在尝试编写将分析 XML 消息的 XSLT 验证规则。我要验证的消息部分的基本构造是

<VXU_V04.ORDER> One or more may be present, not a required group; I’m calling this “OrderGroup”
<ORC> Required; only one ORC Segment per OrderGroup allowed
<ORC.1> Required; only one ORC.1 field per ORC Segment allowed

在我的示例消息中,我有三个&lt;VXU_V04.ORDER&gt; 组。我在下面编写了验证模板。当我使用三个订单组针对我的消息测试我的验证模板时,我没有得到任何输出。我有这个模板的另一个版本,在 ORC 段级别有另一个“for-each”检查,但后来我得到了输出“每个订单组只允许一个订单段 (ORC)”。三次(大概是每个订单组)。测试消息是正确的,因为我每个订单组只有一个 ORC 段,所以显然我的逻辑是错误的。 (某些 ORC.1 值不正确,因此我希望在检查 ORC.1 的值不是“RE”时收到一条消息。)

这是我的验证模板代码:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:a="urn:hl7-org:v2xml" xmlns:dil="http://www.aegis.net/msg/filter/jaxb/rule" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!--      
                Must be 'RE'
         -->
    <xsl:variable name="OrderGroup" select="/a:VXU_V04/a:VXU_V04.ORDER"/>
    <xsl:variable name="ORCSegment" select="/a:VXU_V04/a:VXU_V04.ORDER/a:ORC"/>
    <xsl:variable name="ORC1Field" select="/a:VXU_V04/a:VXU_V04.ORDER/a:ORC/a:ORC.1"/>
    <xsl:template match="/">
        <dil:filterruleresult>
             <xsl:choose>
                 <xsl:when test= "count($OrderGroup)= 0">
                    <dil:message type="info">VXU Order Group not found.</dil:message>
                 </xsl:when>
             </xsl:choose>
             <xsl:for-each select="$OrderGroup">
                     <xsl:choose>
                       <xsl:when test="count(./a:ORC)= 0">  
                          <dil:message type="error">When Order Group present, ORC Segment is required.</dil:message>
                       </xsl:when>
                       <xsl:otherwise>
                          <xsl:for-each select="./a:VXU_V04.ORDER">
                             <xsl:choose>
                                 <xsl:when test="count(./a:ORC)> 0">  
                        <dil:message type="error">Only one Order Segment (ORC) allowed per Order Group.</dil:message>
                                 </xsl:when>
                                 <xsl:when test="count(./a:ORC.1)= 0">
                                <dil:message type="error">ORC-1 Order Control not found but is required.</dil:message>
                                 </xsl:when> 
                                 <xsl:when test="count(./a:ORC.1)> 1">
                                <dil:message type="error">Only one Order Control (ORC-1) allowed per Order Segment.</dil:message>
                                 </xsl:when> 
                                 <xsl:when test="./a:ORC.1!='RE'">
                                <dil:message type="error">ORC-1 Order Control must be equal to 'RE'.  Found '<xsl:value-of select="./a:ORC.1"/>' in message.</dil:message>
                                 </xsl:when>                      
                                 <xsl:when test="./a:ORC.1='RE'">
                                     <dil:message type="info">Valid value of '<xsl:value-of select="./a:ORC.1"/>' found for Order Control (ORC-1).</dil:message>
                                 </xsl:when>
                             </xsl:choose>
                          </xsl:for-each>  
                       </xsl:otherwise>
                      </xsl:choose> 
             </xsl:for-each>      
        </dil:filterruleresult>
    </xsl:template>
</xsl:stylesheet>

这是示例消息:

  <VXU_V04.ORDER>
    <ORC>
      <ORC.1>RE</ORC.1>
      <ORC.3>
        <EI.1>197023</EI.1>
        <EI.2>DCS</EI.2>
      </ORC.3>
      <ORC.10>
        <XCN.2>
          <FN.1>Clerk</FN.1>
        </XCN.2>
        <XCN.3>Myron</XCN.3>
      </ORC.10>
      <ORC.17>
        <CE.1>DCS</CE.1>
        <CE.2>Dabig Clinical System</CE.2>
        <CE.3>StateIIS</CE.3>
      </ORC.17>
    </ORC>
    <RXA>
      <RXA.1>0</RXA.1>
      <RXA.2>1</RXA.2>
      <RXA.3>
        <TS.1>20090415132511</TS.1>
      </RXA.3>
      <RXA.4>
        <TS.1>20090415132511</TS.1>
      </RXA.4>
      <RXA.5>
        <CE.1>31</CE.1>
        <CE.2>Hep B Peds NOS</CE.2>
        <CE.3>CVX</CE.3>
      </RXA.5>
      <RXA.6>999</RXA.6>
      <RXA.9>
        <CE.1>01</CE.1>
        <CE.2>historical record</CE.2>
        <CE.3>NIP0001</CE.3>
      </RXA.9>
    </RXA>
  </VXU_V04.ORDER>
  <VXU_V04.ORDER>
    <ORC>
      <ORC.1>RE</ORC.1>
      <ORC.3>
        <EI.1>197027</EI.1>
        <EI.2>DCS</EI.2>
      </ORC.3>
      <ORC.10>
        <XCN.2>
          <FN.1>Clerk</FN.1>
        </XCN.2>
        <XCN.3>Myron</XCN.3>
      </ORC.10>
      <ORC.12>
        <XCN.2>
          <FN.1>Pediatric</FN.1>
        </XCN.2>
        <XCN.3>MARY</XCN.3>
        <XCN.10>L</XCN.10>
        <XCN.21>MD</XCN.21>
      </ORC.12>
    </ORC>
    <RXA>
      <RXA.1>0</RXA.1>
      <RXA.2>1</RXA.2>
      <RXA.3>
        <TS.1>20090531132511</TS.1>
      </RXA.3>
      <RXA.4>
        <TS.1>20090531132511</TS.1>
      </RXA.4>
      <RXA.5>
        <CE.1>48</CE.1>
        <CE.2>HIB PRP-T</CE.2>
        <CE.3>CVX</CE.3>
      </RXA.5>
      <RXA.6>999</RXA.6>
      <RXA.9>
        <CE.1>00</CE.1>
        <CE.2>new Immunization record</CE.2>
        <CE.3>NIP0001</CE.3>
      </RXA.9>
      <RXA.10>
        <XCN.2>
          <FN.1>Sticker</FN.1>
        </XCN.2>
        <XCN.3>Nurse</XCN.3>
      </RXA.10>
      <RXA.11>
        <LA2.4>
          <HD.1>DCS_DC</HD.1>
        </LA2.4>
      </RXA.11>
      <RXA.15>33k2a</RXA.15>
      <RXA.17>
        <CE.1>PMC</CE.1>
        <CE.2>sanofi</CE.2>
        <CE.3>MVX</CE.3>
      </RXA.17>
    </RXA>
    <RXR>
      <RXR.1>
        <CE.1>C28161</CE.1>
        <CE.2>IM</CE.2>
        <CE.3>NCIT</CE.3>
        <CE.4>IM</CE.4>
        <CE.5>IM</CE.5>
        <CE.6>HL70162</CE.6>
      </RXR.1>
    </RXR>
  </VXU_V04.ORDER>
  <VXU_V04.ORDER>
    <ORC>
      <ORC.1>RE</ORC.1>
      <ORC.3>
        <EI.1>197028</EI.1>
        <EI.2>DCS</EI.2>
      </ORC.3>
      <ORC.10>
        <XCN.2>
          <FN.1>Clerk</FN.1>
        </XCN.2>
        <XCN.3>Myron</XCN.3>
      </ORC.10>
      <ORC.12>
        <XCN.2>
          <FN.1>Pediatric</FN.1>
        </XCN.2>
        <XCN.3>MARY</XCN.3>
        <XCN.10>L</XCN.10>
        <XCN.21>MD</XCN.21>
      </ORC.12>
    </ORC>
    <RXA>
      <RXA.1>0</RXA.1>
      <RXA.2>1</RXA.2>
      <RXA.3>
        <TS.1>20090531132511</TS.1>
      </RXA.3>
      <RXA.4>
        <TS.1>20090531132511</TS.1>
      </RXA.4>
      <RXA.5>
        <CE.1>110</CE.1>
        <CE.2>DTAP-Hep B-IPV</CE.2>
        <CE.3>CVX</CE.3>
      </RXA.5>
      <RXA.6>999</RXA.6>
      <RXA.9>
        <CE.1>00</CE.1>
        <CE.2>new immunization record</CE.2>
        <CE.3>NIP0001</CE.3>
      </RXA.9>
      <RXA.10>
        <XCN.2>
          <FN.1>Sticker</FN.1>
        </XCN.2>
        <XCN.3>Nurse</XCN.3>
      </RXA.10>
      <RXA.11>
        <LA2.4>
          <HD.1>DCS_DC</HD.1>
        </LA2.4>
      </RXA.11>
      <RXA.15>xy3939</RXA.15>
      <RXA.17>
        <CE.1>SKB</CE.1>
        <CE.2>GSK</CE.2>
        <CE.3>MVX</CE.3>
      </RXA.17>
    </RXA>
    <RXR>
      <RXR.1>
        <CE.1>IM</CE.1>
        <CE.2>IM</CE.2>
        <CE.3>HL70162</CE.3>
        <CE.4>C28161</CE.4>
        <CE.5>IM</CE.5>
        <CE.6>NCIT</CE.6>
      </RXR.1>
    </RXR>
  </VXU_V04.ORDER>

任何帮助将不胜感激。

谢谢!

【问题讨论】:

  • 您的 XML 示例缺少一个“根”元素。从您的 XSLT 来看,应该存在“VXU_V04”元素。您可能希望编辑您的问题以显示这一点,特别是因为它看起来有一个“命名空间”声明,如果处理不当,通常会导致问题(尽管看起来您在 XSLT 中处理它很好)。谢谢!
  • 我应该澄清一下,我只粘贴了我的测试消息的 sn-p。它还有更多内容,包括命名空间声明。我一直在使用这段代码,虽然我没有空间粘贴我的新版本,但我现在可以得到错误“当订单组存在时,需要 ORC 段”。对于一个缺失的 ORC 段。但是,我的好段没有得到任何输出。不过,感谢您的回复!

标签: xml validation xslt


【解决方案1】:

也许您应该考虑成为一名程序员,因为您的 XSLT 对于非程序员来说也不错。

无论如何,为了尝试解决问题,您的订单组有一个 xsl:for-each 循环

<xsl:for-each select="$OrderGroup">

这意味着您正在按预期循环遍历 VXU_V04.ORDER 元素。但是在这个循环中,在 xsl:when 条件之一中,您可以执行此操作

<xsl:for-each select="./a:VXU_V04.ORDER">

但这意味着它正在寻找当前 VXU_V04.ORDER 元素的名为 VXU_V04.ORDER 的子元素。我不认为这是你想要的。你已经在循环这些元素,所以你不需要继续循环。

也许您的意思是寻找子 ORC 元素

<xsl:for-each select="a:ORC">

(你不需要在这里加上 ./ 前缀,因为那是默认选择器)。

这将是当前的&lt;xsl:when test="count(./a:ORC)&gt; 0"&gt; 测试需要移出内循环并进入外循环,并更改为测试是否大于 1,但其余条件应该可以工作。

试试这个 XSLT

<xsl:stylesheet version="2.0" xmlns:a="urn:hl7-org:v2xml" xmlns:dil="http://www.aegis.net/msg/filter/jaxb/rule" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!--      
                Must be 'RE'
         -->
    <xsl:variable name="OrderGroup" select="/a:VXU_V04/a:VXU_V04.ORDER"/>
    <xsl:variable name="ORCSegment" select="/a:VXU_V04/a:VXU_V04.ORDER/a:ORC"/>
    <xsl:variable name="ORC1Field" select="/a:VXU_V04/a:VXU_V04.ORDER/a:ORC/a:ORC.1"/>
    <xsl:template match="/">
        <dil:filterruleresult>
             <xsl:choose>
                 <xsl:when test= "count($OrderGroup)= 0">
                    <dil:message type="info">VXU Order Group not found.</dil:message>
                 </xsl:when>
             </xsl:choose>
             <xsl:for-each select="$OrderGroup">
                     <xsl:choose>
                       <xsl:when test="count(a:ORC)= 0">  
                          <dil:message type="error">When Order Group present, ORC Segment is required.</dil:message>
                       </xsl:when>
                       <xsl:when test="count(a:ORC)> 1">  
                        <dil:message type="error">Only one Order Segment (ORC) allowed per Order Group.</dil:message>
                       </xsl:when>
                       <xsl:otherwise>
                          <xsl:for-each select="a:ORC">
                             <xsl:choose>
                                 <xsl:when test="count(a:ORC.1)= 0">
                                <dil:message type="error">ORC-1 Order Control not found but is required.</dil:message>
                                 </xsl:when> 
                                 <xsl:when test="count(a:ORC.1)> 1">
                                <dil:message type="error">Only one Order Control (ORC-1) allowed per Order Segment.</dil:message>
                                 </xsl:when> 
                                 <xsl:when test="a:ORC.1!='RE'">
                                <dil:message type="error">ORC-1 Order Control must be equal to 'RE'.  Found '<xsl:value-of select="./a:ORC.1"/>' in message.</dil:message>
                                 </xsl:when>                      
                                 <xsl:when test="a:ORC.1='RE'">
                                     <dil:message type="info">Valid value of '<xsl:value-of select="./a:ORC.1"/>' found for Order Control (ORC-1).</dil:message>
                                 </xsl:when>
                             </xsl:choose>
                          </xsl:for-each>  
                       </xsl:otherwise>
                      </xsl:choose> 
             </xsl:for-each>      
        </dil:filterruleresult>
    </xsl:template>
</xsl:stylesheet>

当然,&lt;xsl:for-each select="a:ORC"&gt; 有点矫枉过正,因为您已经确认只有一个。理想情况下,您会在此处使用 xsl:apply-templates。也试试这个 XSLT

<xsl:stylesheet version="2.0" xmlns:a="urn:hl7-org:v2xml" xmlns:dil="http://www.aegis.net/msg/filter/jaxb/rule" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!--      
                Must be 'RE'
         -->
    <xsl:variable name="OrderGroup" select="/a:VXU_V04/a:VXU_V04.ORDER"/>
    <xsl:variable name="ORCSegment" select="/a:VXU_V04/a:VXU_V04.ORDER/a:ORC"/>
    <xsl:variable name="ORC1Field" select="/a:VXU_V04/a:VXU_V04.ORDER/a:ORC/a:ORC.1"/>
    <xsl:template match="/">
        <dil:filterruleresult>
             <xsl:choose>
                 <xsl:when test= "count($OrderGroup)= 0">
                    <dil:message type="info">VXU Order Group not found.</dil:message>
                 </xsl:when>
             </xsl:choose>
             <xsl:for-each select="$OrderGroup">
                     <xsl:choose>
                       <xsl:when test="count(./a:ORC)= 0">  
                          <dil:message type="error">When Order Group present, ORC Segment is required.</dil:message>
                       </xsl:when>
                                 <xsl:when test="count(./a:ORC) > 1">  
                        <dil:message type="error">Only one Order Segment (ORC) allowed per Order Group.</dil:message>
                                 </xsl:when>
                       <xsl:otherwise>
                          <xsl:apply-templates select="a:ORC" /> 
                       </xsl:otherwise>
                      </xsl:choose> 
             </xsl:for-each>      
        </dil:filterruleresult>
    </xsl:template>

    <xsl:template match="a:ORC">
           <xsl:choose>
                <xsl:when test="count(./a:ORC.1)= 0">
              <dil:message type="error">ORC-1 Order Control not found but is required.</dil:message>
                </xsl:when> 
                <xsl:when test="count(./a:ORC.1)> 1">
              <dil:message type="error">Only one Order Control (ORC-1) allowed per Order Segment.</dil:message>
                </xsl:when> 
                <xsl:when test="./a:ORC.1!='RE'">
              <dil:message type="error">ORC-1 Order Control must be equal to 'RE'.  Found '<xsl:value-of select="./a:ORC.1"/>' in message.</dil:message>
                </xsl:when>                      
                <xsl:when test="./a:ORC.1='RE'">
                    <dil:message type="info">Valid value of '<xsl:value-of select="./a:ORC.1"/>' found for Order Control (ORC-1).</dil:message>
                </xsl:when>
            </xsl:choose>
    </xsl:template>
</xsl:stylesheet>

如果没有别的,这有嵌套的语句。

【讨论】:

    猜你喜欢
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多