问题
Another Newbie question in XSLT transformation. (I have asked similar question before, but in this case the XML has different formats).
I've a xml document that I need to do bunch of validations using xslt. This will be done using the xsltproc tool.
<?xml version="1.0" ?>
<Company id="1" ...>
<Name>blah</Name>
<Location>
<Address>zzz</Address>
<City>aaa</City>
.....
</Location>
....
<Manager id="m1" mincount="4" grade="10"...>
<Employee id="e1"/>
<Employee id="e2"/>
.....
</Manager>
.....
</Company>
<Employee_List>
<Employee id="e1" grade="9" Location="New York" p1="value" p2="value"....... />
<Employee id="e2" grade="8" Location="New York" p1="value" p2="value"....... />
......
</Employee_List>
I need to do the following validations only for the <Manager>
and <Employee_List>
tags
i.e I do not care about Company Location tags etc. Please note that xml document has <company>
<Employee_List>
tags.
- The number of employees under a Manager should be >= mincount.
- The grades of employees under a manager should be < grade of the Manager.
- All the employees under a Manager should be in te same location. (I need additional checks like property p1 and p2 of employees should match as well).
TIA and appreciate any help!!
New rules to be validated (added on 3/5/12). 1. The p1 attribute must be either ALPHA or BETA (string), it cannot be anything else. This xsl works for a single employee, not for multiple employees.
<xsl:apply-templates mode="rule5" select=
"*/*/Manager[not(key('kEmpById', Employee/@id)/@p1 = 'ALPHA' or
key('kEmpById', Employee/@id)/@p1 = 'BETA')
]
"/>
The employee id under should be unique. I tried this xsl, but it doesn't work :(
<xsl:apply-templates mode="rule6" select=
"//Manager[key('kEmpById', Employee[2]/@id)/@id = key('kEmpById', Employee/@id)/@id ] "/>
TIA!
回答1:
Something like the following:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:key name="kEmpById" match="Employee" use="@id"/>
<xsl:template match="/">
<xsl:apply-templates mode="rule1" select=
"*/*/Manager[@mincount > count(Employee)]"/>
<xsl:apply-templates mode="rule2" select=
"*/*/Manager[key('kEmpById', Employee/@id)/@grade > @grade]"/>
<xsl:apply-templates mode="rule3" select=
"*/*/Manager[key('kEmpById', Employee[2]/@id)/@Location
!=
key('kEmpById', Employee/@id)/@Location
]
"/>
</xsl:template>
<xsl:template match="Manager" mode="rule1">
Manager id = "<xsl:value-of select="@id"/>" has too few employees.
</xsl:template>
<xsl:template match="Manager" mode="rule2">
Manager id = "<xsl:value-of select="@id"/>" has employees with higher grade than his own.
</xsl:template>
<xsl:template match="Manager" mode="rule3">
Manager id = "<xsl:value-of select="@id"/>" has employees at different locations.
</xsl:template>
</xsl:stylesheet>
When this transformation is applied on the provided XML document (edited to remove its severe malformedness and to introduce all possible violations):
<t>
<Company id="1" >
<Name>blah</Name>
<Location>
<Address>zzz</Address>
<City>aaa</City>
</Location>
<Manager id="m1" mincount="4" grade="10">
<Employee id="e1"/>
<Employee id="e2"/>
</Manager>
</Company>
<Employee_List>
<Employee id="e1" grade="11" Location="New York" p1="value" p2="value" />
<Employee id="e2" grade="8" Location="Pittsburgh" p1="value" p2="value" />
</Employee_List>
</t>
the wanted, correct result is produced:
Manager id = "m1" has too few employees.
Manager id = "m1" has employees with higher grade than his own.
Manager id = "m1" has employees at different locations.
来源:https://stackoverflow.com/questions/9505086/xslt-transformation-to-validate-rules-in-xml-document