2012-02-16 64 views
3

我是XSLT的新手。 我有一個XML文檔,我需要拿出xslt來驗證XML文檔中的某些規則。 XML和xsl文件將在xsltproc工具中使用,輸出將是簡單的通過或失敗。新手:XSLT轉換來驗證XML文檔中的規則

示例XML:

...

<Manager mincount="4" grade="10"...> 
    <Employee id="1" grade="9" .... /> 
    <Employee id="2" grade="8" .... /> 
..... 
</Manager> 
  1. 孩子的下經理(員工在這種情況下)的數量必須等於或大於mincount屬性的值。
  2. 所有員工的等級必須小於經理等級。

感謝您的幫助! TIA! TIA!

回答

4

改爲使用XSD架構。它旨在驗證XML。

特別是您可能對XSD 1.1 assertions感興趣。

請參閱http://www.w3schools.com/schema/瞭解更多教程。

+0

+1 XSLT用於XML文檔的轉換。 本教程應該很好的學習如何驗證 – 2012-02-16 06:17:28

+3

加入傢伙,同時提供符合Foo Bar要求的XSD代碼片段。 – Maestro13 2012-02-16 06:37:28

+2

據我所知,在XSD規範中,只能提供等於非負整數的minOccurs屬性值。但是這裏需要引用父元素中的屬性。 是否有更新版本的XSD,我不知道,可以做到這一點? 如果不是,那麼這個問題是有效的,適用於XSLT。 – Maestro13 2012-02-16 07:14:17

0

下面是一個XSLT,它檢查mincount值與Employee的實際發生次數。請注意,使用了xsl:function,因此需要XSLT 2.0。

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:custom="http://localhost:8080/customFunctions" exclude-result-prefixes="custom"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:function name="custom:checkMgr"> 
     <xsl:param name="mgr"/> 
     <xsl:choose> 
      <xsl:when test="$mgr/@mincount &gt; count($mgr/Employee)">false</xsl:when> 
      <xsl:when test="count($mgr/Employee[number(@grade) &gt;= number($mgr/@grade)]) &gt; 0">false</xsl:when> 
      <xsl:otherwise>true</xsl:otherwise> 
     </xsl:choose> 
    </xsl:function> 

    <xsl:template match="/"> 
     <root> 
      <xsl:apply-templates select="root/Manager"/> 
     </root> 
    </xsl:template> 

    <xsl:template match="Manager"> 
     <mgrCheck> 
      <xsl:attribute name="id" select="@id"/> 
      <xsl:attribute name="mincount" select="@mincount"/> 
      <xsl:attribute name="actual" select="count(Employee)"/> 
      <xsl:attribute name="grade" select="@grade"/> 
      <xsl:attribute name="numEmpNoLessGrade" select="count(Employee[number(@grade) >= number(../@grade)])"/> 
      <xsl:attribute name="OK" select="custom:checkMgr (.)"/> 
     </mgrCheck> 
    </xsl:template> 
</xsl:stylesheet> 

當施加在下列輸入:

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <Manager mincount="4" grade="10" id="26"> 
     <Employee id="1" grade="9"/> 
     <Employee id="2" grade="8"/> 
    </Manager> 
    <Manager mincount="1" grade="10" id="27"> 
     <Employee id="3" grade="9"/> 
     <Employee id="4" grade="8"/> 
     <Employee id="5" grade="4"/> 
    </Manager> 
    <Manager mincount="1" grade="7" id="28"> 
     <Employee id="6" grade="8"/> 
     <Employee id="7" grade="7"/> 
     <Employee id="8" grade="6"/> 
     <Employee id="9" grade="9"/> 
    </Manager> 
    <Manager mincount="3" grade="9" id="29"> 
     <Employee id="10" grade="9"/> 
     <Employee id="11" grade="8"/> 
     <Employee id="12" grade="7"/> 
    </Manager> 
</root> 

結果是:

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <mgrCheck id="26" mincount="4" actual="2" grade="10" numEmpNoLessGrade="0" OK="false"/> 
    <mgrCheck id="27" mincount="1" actual="3" grade="10" numEmpNoLessGrade="0" OK="true"/> 
    <mgrCheck id="28" mincount="1" actual="4" grade="7" numEmpNoLessGrade="3" OK="false"/> 
    <mgrCheck id="29" mincount="3" actual="3" grade="9" numEmpNoLessGrade="1" OK="false"/> 
</root> 

在XSLT 1.0的另一種可能是以下內容:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:template match="/"> 
     <root> 
      <xsl:apply-templates select="root/Manager"/> 
     </root> 
    </xsl:template> 

    <xsl:template match="Manager"> 
     <mgrCheck> 
      <id><xsl:value-of select="@id"/></id> 
      <mincount><xsl:value-of select="@mincount"/></mincount> 
      <actual><xsl:value-of select="count(Employee)"/></actual> 
      <grade><xsl:value-of select="@grade"/></grade> 
      <numEmpNoLessGrade><xsl:value-of select="count(Employee[@grade &gt;= ../@grade])"/></numEmpNoLessGrade> 
      <OK> 
       <xsl:choose> 
        <xsl:when test="@mincount &gt; count(Employee)">false</xsl:when> 
        <xsl:when test="count(Employee[@grade &gt;= ../@grade]) &gt; 0">false</xsl:when> 
        <xsl:otherwise>true</xsl:otherwise> 
       </xsl:choose> 
      </OK> 
     </mgrCheck> 
    </xsl:template> 
</xsl:stylesheet> 

與結果

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <mgrCheck> 
     <id>26</id> 
     <mincount>4</mincount> 
     <actual>2</actual> 
     <grade>10</grade> 
     <numEmpNoLessGrade>0</numEmpNoLessGrade> 
     <OK>false</OK> 
    </mgrCheck> 
    <mgrCheck> 
     <id>27</id> 
     <mincount>1</mincount> 
     <actual>3</actual> 
     <grade>10</grade> 
     <numEmpNoLessGrade>0</numEmpNoLessGrade> 
     <OK>true</OK> 
    </mgrCheck> 
    <mgrCheck> 
     <id>28</id> 
     <mincount>1</mincount> 
     <actual>4</actual> 
     <grade>7</grade> 
     <numEmpNoLessGrade>3</numEmpNoLessGrade> 
     <OK>false</OK> 
    </mgrCheck> 
    <mgrCheck> 
     <id>29</id> 
     <mincount>3</mincount> 
     <actual>3</actual> 
     <grade>9</grade> 
     <numEmpNoLessGrade>1</numEmpNoLessGrade> 
     <OK>false</OK> 
    </mgrCheck> 
</root> 
+1

在第一個示例中,您可以將函數更改爲命名模板,然後將其作爲XSL 1.0。儘管如此,您還必須從「xsl:attribute」元素中選取「select」屬性。這將通過使用AVT(http://www.w3.org/TR/xslt#attribute-value-templates)來處理。 – 2012-02-16 16:23:46

+0

非常感謝。非常感激!我發佈了另一個類似的問題,輸入XML文檔的一些變化,http://stackoverflow.com/questions/9505086/xslt-transformation-to-validate-rules-in-xml-document。 – 2012-02-29 19:27:36

2

下面是一個XSLT 1.0選項,其中顯示合格/不合格。 「失敗」中還有其他詳細信息,但可以刪除。它還將消息輸出到stdout和stderr並終止處理。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="text"/> 

    <xsl:template match="/Manager"> 
    <xsl:if test="not(count(Employee) >= @mincount)"> 
     <xsl:variable name="vMessage" select="concat('Fail - Number of Employees (',count(Employee),') is not >= to @mincount (',@mincount,').')"/> 
     <!--stdout--> 
     <xsl:value-of select="$vMessage" disable-output-escaping="yes"/> 
     <!--stderr--> 
     <xsl:message terminate="yes"><xsl:value-of select="$vMessage"/></xsl:message> 
    </xsl:if> 
    <xsl:if test="Employee/@grade >= @grade"> 
     <xsl:variable name="vMessage" select="concat('Fail - Employee (id ',Employee[@grade >= ancestor::Manager/@grade][1]/@id,') has a grade (',Employee[@grade >= ancestor::Manager/@grade][1]/@grade,') that is higher than the Manager grade (',@grade,').')"/> 
     <!--stdout--> 
     <xsl:value-of select="$vMessage" disable-output-escaping="yes"/> 
     <!--stderr--> 
     <xsl:message terminate="yes"><xsl:value-of select="$vMessage"/></xsl:message> 
    </xsl:if> 
    <xsl:text>Pass</xsl:text> 
    </xsl:template> 

</xsl:stylesheet> 

這裏有一些XML /輸出的例子:

<Manager mincount="1" grade="7" id="28"> 
    <Employee id="6" grade="5"/> 
    <Employee id="7" grade="1"/> 
    <Employee id="8" grade="2"/> 
    <Employee id="3" grade="7"/> 
</Manager> 

Fail - Employee (id 3) has a grade (7) that is higher than the Manager grade (7). 

<Manager mincount="1" grade="7" id="28"> 
    <Employee id="6" grade="5"/> 
    <Employee id="7" grade="1"/> 
    <Employee id="8" grade="2"/> 
    <Employee id="3" grade="6"/> 
</Manager> 

Pass 

<Manager mincount="10" grade="7" id="28"> 
    <Employee id="6" grade="5"/> 
    <Employee id="7" grade="1"/> 
    <Employee id="8" grade="2"/> 
    <Employee id="3" grade="6"/> 
</Manager> 

Fail - Number of Employees (4) is not >= to @mincount (10).