2012-02-16 2 views
3

私はXSLTの初心者です。 私はXML文書を持っており、XML文書の特定の規則を検証するためにxsltを用意する必要があります。 XMLとxslファイルはxsltprocツールで使用され、出力は単純な合格または失敗になります。初心者:XML文書のルールを検証するためのXSLT変換

サンプルXML:

...

<Manager mincount="4" grade="10"...> 
    <Employee id="1" grade="9" .... /> 
    <Employee id="2" grade="8" .... /> 
..... 
</Manager> 
  1. マネージャーの下で子供(この場合は従業員)の数に等しいかMINCOUNT属性の値よりも大きくなければなりません。
  2. 従業員のすべての成績は、マネージャの成績より低くする必要があります。

あなたの助けをお待ちしています! TIA!

答えて

4

代わりにXSDスキーマを使用してください。 XMLを検証するために設計されています。

特にXSD 1.1 assertionsに興味があります。

良いチュートリアルについては、http://www.w3schools.com/schema/を参照してください。

+0

1 XSLTは、XML文書の形質転換のために使用されます。 チュートリアルは、 –

+3

の妥当性確認の方法を学ぶのに適している必要があります。Foo Barの要件を満たすXSDスニペットも提供してください。 – Maestro13

+2

私が知る限り、XSD仕様では、負でない整数に等しいminOccurs属性値しか供給できません。しかしここでは、親要素の属性を参照する必要があります。 わからないXSDの新しいバージョンがありますか? そうでない場合、質問は有効なものであり、XSLTに適しています。 – Maestro13

0

ここでは、分数の値とEmployeeの実際の発生数をチェックするXSLTがあります。 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)を使用して処理されます。 –

+0

ありがとうたくさんの人。とても有難い!私は入力XMLドキュメントのいくつかのバリエーションで、もう1つ同様の質問を投稿しました。http://stackoverflow.com/questions/9505086/xslt-transformation-to-validate-rules-in-xml-document –

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). 
関連する問題