我有一个大致如下的XML文件:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Multiple xmlns:ns2="someNs2" xmlns="someGenericNs" xmlns:ns4="someNs4" xmlns:ns3="someNs3">
<Single>
<Id>60000</Id>
<Type>Activate</Type>
<Payload>
<ns3:Activation>
<ns3:Parent>
<ns3:TypeId>113</ns3:TypeId>
<ns3:TypeName>TestApplication</ns3:TypeName>
</ns3:Parent>
<ns3:Children>
<ns3:Child>
<ns3:Key>someKey</ns3:Key>
<ns3:ChildTypeName>BadAppType1</ns3:ChildTypeName>
</ns3:Child>
<ns3:Child>
<ns3:Key>someOtherKey</ns3:Key>
<ns3:ChildTypeName>GoodAppType1</ns3:ChildTypeName>
</ns3:Child>
</ns3:Children>
</ns3:Activation>
</Payload>
</Single>
</Multiple>
我需要做的是将其转换为更简单的形式,如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<MyNewRootNode xmlns="MyNewNamespace">
<Activation>
<ApplicationType>TestApplication</ApplicationType>
<ValidChildTypeName>GoodAppType1</ValidChildTypeName>
<ValidChildKey>someOtherKey</ValidChildKey>
</Activation>
</MyNewRootNode>
初始XML可以包含多个子节点,其中只有一个具有有效的“CildTypeName”节点。我的问题是,如果XML确实包含多个子节点,那么我的XSLT将只抓取第一个并将其转换为新格式,即使它包含无效的“ChildTypeName”。
总结一下:我需要将XML转换为更简单的形式。要创建这个更简单的表单,我需要筛选所有“子”节点并找到包含有效“ChildTypeName”的节点,并将其“Key”和“ChildTypeName”的值复制到新节点XML。
我还有一个有效“ChildTypeNames”的预定义列表。它包含大约3个名字,不会很快改变。
这是我到目前为止所学到的XSLT:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="MyNewNamespace" xmlns:ns3="someNs3" exclude-result-prefixes="ns3">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="activationNode">
<xsl:text>Activation</xsl:text>
</xsl:variable>
<xsl:variable name="new-root-node">
<xsl:text>MyNewRootNode</xsl:text>
</xsl:variable>
<xsl:template match="/*">
<xsl:element name="{$new-root-node}">
<xsl:element name="{$activationNode}">
<xsl:call-template name="TemplateOne"/>
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template name="TemplateOne">
<xsl:element name="ApplicationType">
<xsl:value-of select="//ns3:Activation/ns3:Parent/ns3:TypeName"/>
</xsl:element>
<xsl:element name="ValidChildTypeName">
<xsl:value-of select="//ns3:Activation/ns3:Children/ns3:Child/ns3:ChildTypeName"/>
</xsl:element>
<xsl:element name="ValidChildKey">
<xsl:value-of select="//ns3:Activation/ns3:Children/ns3:Child/ns3:Key"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
但是这将抓住它找到的第一个子节点,在这种情况下是“BadAppType1”。
更新:在此方面取得了一些进展。将XSLT的最后一部分更改为:
<xsl:for-each select="//ns3:Activation/ns3:Children/ns3:Child">
<xsl:if test="ns3:ChildTypeName[text()='GoodAppType1']">
<xsl:element name="ValidChildTypeName">
<xsl:value-of select="ns3:ChildTypeName"/>
</xsl:element>
<xsl:element name="ValidChildKey">
<xsl:value-of select="ns3:Key"/>
</xsl:element>
</xsl:if>
</xsl:for-each>
据我所知,我只需要一种方法来检查多个可能的有效值,它应该是正确的。
答案 0 :(得分:1)
如果您尝试选择激活元素,其 Child 元素的 ChildTypeName 为&#34; GoodAppType1&#34;那么也许你可以使用模板匹配来选择它存在的元素。
<xsl:apply-templates
select="//ns3:Activation[ns3:Children/ns3:Child/ns3:ChildTypeName='GoodAppType1']" />
然后,在与此匹配的模板中,您可以轻松输出 ApplicationType
<ApplicationType><xsl:value-of select="ns3:Parent/ns3:TypeName" /></ApplicationType>
然后,选择包含 ChildTypeName
的 Child 元素<xsl:apply-templates select="ns3:Children/ns3:Child[ns3:ChildTypeName='GoodAppType1']" />
在匹配儿童的模板中,您同样可以输出键和 ChildTypeName 。
尝试以下XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="MyNewNamespace" xmlns:ns3="someNs3" exclude-result-prefixes="ns3">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="activationNode">
<xsl:text>Activation</xsl:text>
</xsl:variable>
<xsl:variable name="new-root-node">
<xsl:text>MyNewRootNode</xsl:text>
</xsl:variable>
<xsl:template match="/">
<xsl:element name="{$new-root-node}">
<xsl:apply-templates select="//ns3:Activation[ns3:Children/ns3:Child/ns3:ChildTypeName='GoodAppType1']"/>
</xsl:element>
</xsl:template>
<xsl:template match="ns3:Activation">
<xsl:element name="{$activationNode}">
<ApplicationType>
<xsl:value-of select="ns3:Parent/ns3:TypeName"/>
</ApplicationType>
<xsl:apply-templates select="ns3:Children/ns3:Child[ns3:ChildTypeName='GoodAppType1']"/>
</xsl:element>
</xsl:template>
<xsl:template match="ns3:Child">
<ValidChildTypeName>
<xsl:value-of select="ns3:ChildTypeName"/>
</ValidChildTypeName>
<ValidChildKey>
<xsl:value-of select="ns3:Key"/>
</ValidChildKey>
</xsl:template>
</xsl:stylesheet>
针对输入XML运行时,输出以下内容
<MyNewRootNode xmlns="MyNewNamespace">
<Activation>
<ApplicationType>TestApplication</ApplicationType>
<ValidChildTypeName>GoodAppType1</ValidChildTypeName>
<ValidChildKey>someOtherKey</ValidChildKey>
</Activation>
</MyNewRootNode>