#xml #xslt #xslt-1.0
#xml #xslt #xslt-1.0
Вопрос:
У меня есть требование находить повторяющиеся и пустые узлы вместо удаления их из XML, поэтому я написал ниже XSL и могу получить список пустых узлов, прочитав XML.Но я не могу получить результат, если существует дублирующий узел. нужна ваша помощь, чтобы достичь этого.
ниже приведен входной XML-файл:
<p:Organisation xmlns:p="http://www.tibco.com/schemas/prjDelimeter/Schema/Schema2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.tibco.com/schemas/prjDelimeter/Schema/Schema2.xsd HeaderRecords.xsd ">
<p:EMP>
<p:ID>123</p:ID>
<p:Name>uday</p:Name>
<p:Designation>SoftwareEng</p:Designation>
<p:ExpertiseIn>SOA,OSB,TIBCO</p:ExpertiseIn>
</p:EMP>
<p:ASSETS>
<p:ASSET>
<p:AssetID>1000</p:AssetID>
<p:Name>Ego</p:Name>
<p:InUse>yes</p:InUse>
<p:AssignedDate>2005</p:AssignedDate>
</p:ASSET>
<p:ASSET>
<p:AssetID>2000</p:AssetID>
<p:Name>HP</p:Name>
<p:InUse></p:InUse>
<p:AssignedDate>2002</p:AssignedDate>
</p:ASSET>
<p:ASSET>
<p:AssetID>3000</p:AssetID>
<p:Name>Dell</p:Name>
<p:InUse>yes</p:InUse>
<p:AssignedDate>2010</p:AssignedDate>
</p:ASSET>
<p:ASSET>
<p:AssetID>4000</p:AssetID>
<p:Name></p:Name>
<p:InUse>yes</p:InUse>
<p:AssignedDate>2009</p:AssignedDate>
</p:ASSET>
<p:ASSET>
<p:AssetID>3000</p:AssetID>
<p:Name>Lenovo</p:Name>
<p:InUse>yes</p:InUse>
<p:AssignedDate>2011</p:AssignedDate>
</p:ASSET>
</p:ASSETS>
</p:Organisation>
а ниже приведен текущий результат, который я получаю, если вижу какие-либо пустые узлы:
InUse in Line- 2 with Position-3 is empty
Name in Line- 4 with Position-2 is empty
ниже приведен ожидаемый результат :
InUse in Line- 2 with Position-3 is empty
Name in Line- 4 with Position-2 is empty
Found Duplicate Asset ID's
ниже приведен XSLT, с которым я работал и смог получить список пустых узлов:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:p="http://www.tibco.com/schemas/prjDelimeter/Schema/Schema2.xsd">
<xsl:output omit-xml-declaration="yes" />
<xsl:template match="/">
<xsl:apply-templates mode="rule1"
select="p:Organisation/p:EMP/p:ID">
</xsl:apply-templates>
<xsl:apply-templates mode="rule2"
select="p:Organisation/p:EMP/p:Name">
</xsl:apply-templates>
<xsl:apply-templates mode="rule3"
select="p:Organisation/p:EMP/p:Designation">
</xsl:apply-templates>
<xsl:apply-templates mode="rule4"
select="p:Organisation/p:EMP/p:ExpertiseIn">
</xsl:apply-templates>
<xsl:apply-templates mode="rule5"
select="p:Organisation/p:ASSETS">
</xsl:apply-templates>
</xsl:template>
<!-- Employee data Validation -->
<xsl:template match="p:ID" mode="rule1">
<xsl:if test="current() = ''">
Employee ID is empty.
</xsl:if>
</xsl:template>
<xsl:template match="p:Name" mode="rule2">
<xsl:if test="current() = ''">
Employee Name is empty.
</xsl:if>
</xsl:template>
<xsl:template match="p:Designation" mode="rule3">
<xsl:if test="current() = ''">
Employee Designation is empty.
</xsl:if>
</xsl:template>
<xsl:template match="p:ExpertiseIn" mode="rule4">
<xsl:if test="current() = ''">
ExpertiseIn data can't be empty.
</xsl:if>
</xsl:template>
<!-- Assets data Validation -->
<xsl:template match="p:ASSETS/*" mode='rule5'>
<xsl:variable name="i" select="count(preceding-sibling::*) 1" />
<xsl:for-each select="child::*">
<xsl:if test="current() = '' ">
<xsl:value-of select="local-name()" /> in Line- <xsl:value-of select="$i" /> with Position-<xsl:value-of select="count(preceding-sibling::*) 1" /> is empty
</xsl:if>
</xsl:for-each>
</xsl:template>
пожалуйста, помогите мне также найти дублирующиеся узлы.
Спасибо за вашу помощь.
Комментарии:
1. Пожалуйста, покажите нам ожидаемый результат.
2. спасибо за ваш ответ, Майкл, я добавил ожидаемый результат в сообщение. пожалуйста, посмотрите.
3. Вам даже не нужен какой-либо условный оператор XSLT — подробности см. В моем ответе.
Ответ №1:
Это короткое и простое преобразование создает разделенный пробелом список всех p:AssetID
элементов, которые имеют повторяющиеся значения:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:p="http://www.tibco.com/schemas/prjDelimeter/Schema/Schema2.xsd">
<xsl:output method="text"/>
<xsl:key name="kAsseIdByVal" match="p:AssetID" use="."/>
<xsl:template match="p:AssetID[generate-id()=generate-id(key('kAsseIdByVal', .)[2])]">
<xsl:value-of select="concat(., ' ')"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
При применении к этому XML-документу (предоставленный один еще один pAsset
элемент, чтобы иметь еще одну группу повторяющихся значений):
<p:Organisation xmlns:p="http://www.tibco.com/schemas/prjDelimeter/Schema/Schema2.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.tibco.com/schemas/prjDelimeter/Schema/Schema2.xsd HeaderRecords.xsd ">
<p:EMP>
<p:ID>123</p:ID>
<p:Name>uday</p:Name>
<p:Designation>SoftwareEng</p:Designation>
<p:ExpertiseIn>SOA,OSB,TIBCO</p:ExpertiseIn>
</p:EMP>
<p:ASSETS>
<p:ASSET>
<p:AssetID>1000</p:AssetID>
<p:Name>Ego</p:Name>
<p:InUse>yes</p:InUse>
<p:AssignedDate>2005</p:AssignedDate>
</p:ASSET>
<p:ASSET>
<p:AssetID>2000</p:AssetID>
<p:Name>HP</p:Name>
<p:InUse></p:InUse>
<p:AssignedDate>2002</p:AssignedDate>
</p:ASSET>
<p:ASSET>
<p:AssetID>3000</p:AssetID>
<p:Name>Dell</p:Name>
<p:InUse>yes</p:InUse>
<p:AssignedDate>2010</p:AssignedDate>
</p:ASSET>
<p:ASSET>
<p:AssetID>4000</p:AssetID>
<p:Name></p:Name>
<p:InUse>yes</p:InUse>
<p:AssignedDate>2009</p:AssignedDate>
</p:ASSET>
<p:ASSET>
<p:AssetID>3000</p:AssetID>
<p:Name>Lenovo</p:Name>
<p:InUse>yes</p:InUse>
<p:AssignedDate>2011</p:AssignedDate>
</p:ASSET>
<p:ASSET>
<p:AssetID>4000</p:AssetID>
<p:Name></p:Name>
<p:InUse>yes</p:InUse>
<p:AssignedDate>2009</p:AssignedDate>
</p:ASSET>
</p:ASSETS>
</p:Organisation>
получен требуемый правильный результат:
3000 4000
Ответ №2:
Чтобы свести пример к рассматриваемой проблеме, рассмотрим следующую таблицу стилей:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:p="http://www.tibco.com/schemas/prjDelimeter/Schema/Schema2.xsd">
<xsl:output method="text" encoding="UTF-8" />
<xsl:key name="asset" match="p:ASSET" use="p:AssetID" />
<xsl:template match="/p:Organisation">
<!-- other stuff -->
<xsl:if test="p:ASSETS/p:ASSET[count(key('asset', p:AssetID)) > 1]">Found Duplicate Asset ID's</xsl:if>
</xsl:template>
</xsl:stylesheet>
Комментарии:
1. это мне очень помогло, Майкл, до сих пор я пытался добиться этого, используя generate-id()=key(«,.). но это действительно сработало для меня
Ответ №3:
я только что понял, что даже мы можем выполнить это требование с помощью концепции generate-id (), как показано ниже:
<xsl:if test="p:ASSETS/p:ASSET[generate-id()= generate-id(key('asset',p:AssetID)[2])]">Found Duplicate Asset ID's</xsl:if>