在 XSLT 中处理多个条件循环
Handling multiple Conditional Looping in XSLT
我有一个示例消息,必须使用 XSLT 将其转换为不同的输出结构。
收到的消息是
<document>
<ObjectId>
<ID>1000909090</ID>
<dlex>
<attrGroupMany name="streetinfo">
<row> <!-- Mandatory Loop -->
<attr name="streetcode">AS_DRAINED</attr>
<attrQualMany name="streetintake"> <!-- Optional Loop -->
<value qual="en">dvif1</value>
<value qual="nl">dvif2</value>
</attrQualMany>
<attr name="streettype">BY_MEASURE</attr>
<attrQual name="streetbasis" qual="ONZ">5</attrQual>
<attrQual name="streetsize" qual="EA">1</attrQual>
<attrQualMany name="streetsizeDescription"> <!-- Optional Loop -->
<value qual="en">sz1</value>
<value qual="hi">sz2</value>
</attrQualMany>
<attrGroupMany name="streetDetails">
<row> <!-- Optional Loop -->
<attr name="streetTypeCode">FAT</attr>
<attr name="streetValueIntakePercent">25</attr>
<attr name="streetPrecisionCode">APPROXIMATELY</attr>
<attrQualMany name="streetContained"> <!-- Optional Loop -->
<value qual="ONZ">2</value>
<value qual="OZA">3</value>
</attrQualMany>
</row>
<row>
<attr name="streetTypeCode">FAMS</attr>
<attr name="streetValueIntakePercent">999</attr>
<attr name="streetPrecisionCode">EXACT</attr>
<attrQualMany name="streetContained">
<value qual="ONZ">4</value>
<value qual="OZA">5</value>
</attrQualMany>
</row>
</attrGroupMany>
</row>
</attrGroupMany>
</dlex>
</ObjectId>
</document>
输出消息是
<?xml version="1.0" encoding="UTF-8"?>
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAMS-5-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAMS-5-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAMS-5-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAMS-5-OZA" />
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
当我们使用下面的 XSLT 时,它工作得很好。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="document">
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<xsl:for-each select="ObjectId/dlex/attrGroupMany[@name='streetinfo']/row">
<xsl:variable name="v_position_streetinfo" select="position()" />
<xsl:variable name="v_streetcode">
<xsl:value-of select="attr[@name='streetcode'])"/>
</xsl:variable>
<xsl:variable name="v_streetintake" select="attrQualMany[@name = 'streetintake']/value" />
<xsl:variable name="v_streetsizeDescription" select="attrQualMany[@name = 'streetsizeDescription']/value" />
<xsl:variable name="v_streetDetails" select="attrGroupMany[@name = 'streetDetails']/row" />
<xsl:for-each select="$v_streetintake">
<xsl:variable name="v_streetintakevalue" select="." />
<xsl:variable name="v_streetintakequal" select="./@qual" />
<xsl:for-each select="$v_streetsizeDescription">
<xsl:variable name="v_streetsizeDescriptionvalue" select="." />
<xsl:variable name="v_streetsizeDescriptionqual" select="./@qual" />
<xsl:for-each select="$v_streetDetails">
<xsl:variable name="v_streetTypeCode">
<xsl:value-of select="attr[@name='streetTypeCode'])"/>
</xsl:variable>
<xsl:variable name="v_streetContained" select="attrQualMany[@name = 'streetContained']/value" />
<xsl:for-each select="$v_streetContained">
<xsl:variable name="v_streetContainedvalue" select="." />
<xsl:variable name="v_streetContainedqual" select="./@qual" />
<RelatedObjectId>
<xsl:attribute name="referenceKey">
<xsl:value-of select="concat('ObjectId_Street','-',$v_position_streetinfo,'-',$v_streetcode,'-',$v_streetintakevalue,'-',$v_streetintakequal,'-',$v_streetsizeDescriptionvalue,'-',$v_streetsizeDescriptionqual,'-',$v_streetTypeCode,'-',$v_streetContainedvalue,'-',$v_streetContainedqual)"/>
</xsl:attribute>
</RelatedObjectId>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
</xsl:template>
</xsl:stylesheet>
但是当任何一个可选循环都没有出现时,它就不起作用了。当所有可选循环都存在时,我已经编写了 XSLT,当消息中出现可选组的任何 1 或 2 或 3 或 none 时,我如何编写 XSLT。请建议
预期输出
当第一个可选组不存在时,输出将有8条记录。
<?xml version="1.0" encoding="UTF-8"?>
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAMS-5-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAMS-5-OZA" />
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
当第一个和第二个可选组不存在时,输出将有4条记录。
<?xml version="1.0" encoding="UTF-8"?>
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAMS-5-OZA" />
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
好的。我不确定我是否完全理解您的预期输出。您的示例列出了 4 个可选循环,而不是两个,而且我不确定示例输出中缺少组的 "en" 来自哪里。
但是,这可以帮助您入门。我没有尝试在嵌套 for-each 结构中汇总所有内容,而是在类似于递归下降解析器的结构中使用多个模板。在每个级别,代码都会检查可选元素并在它们周围循环或跳到下一个级别。 referenceKey-strings 作为参数传递并在我们向下构建时构建。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/document">
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<xsl:for-each select="ObjectId/dlex/attrGroupMany[@name='streetinfo']">
<xsl:variable name="pos" select="position()"/>
<xsl:apply-templates select="row" mode="streetintake">
<xsl:with-param name="referenceKey" select="concat('ObjectId_Street-',$pos)" />
</xsl:apply-templates>
</xsl:for-each>
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
</xsl:template>
<xsl:template match="row" mode="streetintake">
<xsl:param name="referenceKey" />
<xsl:variable name="streetcode" select="concat($referenceKey,'-',attr[@name='streetcode'],'-')"/>
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetintake']/value">
<xsl:for-each select="attrQualMany[@name='streetintake']/value">
<xsl:apply-templates select="../.." mode="streetsize">
<xsl:with-param name="referenceKey" select="concat($streetcode,text(),'-',@qual)" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="streetsize">
<xsl:with-param name="referenceKey" select="$streetcode" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="streetsize">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetsizeDescription']/value">
<xsl:for-each select="attrQualMany[@name='streetsizeDescription']/value">
<xsl:apply-templates select="../../attrGroupMany[@name='streetDetails']" mode="streetdetails">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="attrGroupMany[@name='streetDetails']" mode="streetdetails">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="attrGroupMany" mode="streetdetails">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="row">
<xsl:apply-templates select="row" mode="streetdetails">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',row/attr[@name='streetTypeCode'])" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="streetdetails">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetContained']">
<xsl:apply-templates select="attrQualMany[@name='streetContained']">
<xsl:with-param name="referenceKey" select="$referenceKey"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="attrQualMany[@name='streetContained']">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="value">
<xsl:for-each select="value">
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" />
</xsl:call-template>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="RelatedObjectId">
<xsl:param name="referenceKey" />
<RelatedObjectId>
<xsl:attribute name="referenceKey"><xsl:value-of select="$referenceKey"/></xsl:attribute>
</RelatedObjectId>
</xsl:template>
</xsl:stylesheet>
我在现有代码中添加了更多片段,以处理所有可选组都缺失或完整
时的空情况
<attrGroupMany name="streetDetails"> details are missing.
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/document">
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<xsl:for-each select="ObjectId/dlex/attrGroupMany[@name='streetinfo']">
<xsl:variable name="pos" select="position()"/>
<xsl:apply-templates select="row" mode="streetintake">
<xsl:with-param name="referenceKey" select="concat('ObjectId_Street-',$pos)" />
</xsl:apply-templates>
</xsl:for-each>
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
</xsl:template>
<xsl:template match="row" mode="streetintake">
<xsl:param name="referenceKey" />
<xsl:variable name="streetcode" select="concat($referenceKey,'-',attr[@name='streetcode'],'-')"/>
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetintake']/value">
<xsl:for-each select="attrQualMany[@name='streetintake']/value">
<xsl:apply-templates select="../.." mode="streetsize">
<xsl:with-param name="referenceKey" select="concat($streetcode,text(),'-',@qual)" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="streetsize">
<xsl:with-param name="referenceKey" select="$streetcode" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="streetsize">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetsizeDescription']/value">
<xsl:choose>
<xsl:when test="attrGroupMany[@name='streetDetails']">
<xsl:for-each select="attrQualMany[@name='streetsizeDescription']/value">
<xsl:apply-templates select="../../attrGroupMany[@name='streetDetails']" mode="streetdetails">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="attrQualMany[@name='streetsizeDescription']/value">
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" />
</xsl:call-template>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:if test="not(attrQualMany[@name='streetintake']) and not(attrQualMany[@name='streetsizeDescription']) and not(attrGroupMany[@name='streetDetails'])">
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:if>
<xsl:apply-templates select="attrGroupMany[@name='streetDetails']" mode="streetdetails">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="attrGroupMany" mode="streetdetails">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="row">
<xsl:apply-templates select="row" mode="streetdetails">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',row/attr[@name='streetTypeCode'])" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="streetdetails">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetContained']">
<xsl:apply-templates select="attrQualMany[@name='streetContained']">
<xsl:with-param name="referenceKey" select="$referenceKey"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="attrQualMany[@name='streetContained']">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="value">
<xsl:for-each select="value">
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" />
</xsl:call-template>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="RelatedObjectId">
<xsl:param name="referenceKey" />
<RelatedObjectId>
<xsl:attribute name="referenceKey">
<xsl:value-of select="$referenceKey"/>
</xsl:attribute>
</RelatedObjectId>
</xsl:template>
我有一个示例消息,必须使用 XSLT 将其转换为不同的输出结构。
收到的消息是
<document>
<ObjectId>
<ID>1000909090</ID>
<dlex>
<attrGroupMany name="streetinfo">
<row> <!-- Mandatory Loop -->
<attr name="streetcode">AS_DRAINED</attr>
<attrQualMany name="streetintake"> <!-- Optional Loop -->
<value qual="en">dvif1</value>
<value qual="nl">dvif2</value>
</attrQualMany>
<attr name="streettype">BY_MEASURE</attr>
<attrQual name="streetbasis" qual="ONZ">5</attrQual>
<attrQual name="streetsize" qual="EA">1</attrQual>
<attrQualMany name="streetsizeDescription"> <!-- Optional Loop -->
<value qual="en">sz1</value>
<value qual="hi">sz2</value>
</attrQualMany>
<attrGroupMany name="streetDetails">
<row> <!-- Optional Loop -->
<attr name="streetTypeCode">FAT</attr>
<attr name="streetValueIntakePercent">25</attr>
<attr name="streetPrecisionCode">APPROXIMATELY</attr>
<attrQualMany name="streetContained"> <!-- Optional Loop -->
<value qual="ONZ">2</value>
<value qual="OZA">3</value>
</attrQualMany>
</row>
<row>
<attr name="streetTypeCode">FAMS</attr>
<attr name="streetValueIntakePercent">999</attr>
<attr name="streetPrecisionCode">EXACT</attr>
<attrQualMany name="streetContained">
<value qual="ONZ">4</value>
<value qual="OZA">5</value>
</attrQualMany>
</row>
</attrGroupMany>
</row>
</attrGroupMany>
</dlex>
</ObjectId>
</document>
输出消息是
<?xml version="1.0" encoding="UTF-8"?>
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz1-en-FAMS-5-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif1-en-sz2-hi-FAMS-5-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz1-en-FAMS-5-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED-dvif2-nl-sz2-hi-FAMS-5-OZA" />
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
当我们使用下面的 XSLT 时,它工作得很好。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="document">
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<xsl:for-each select="ObjectId/dlex/attrGroupMany[@name='streetinfo']/row">
<xsl:variable name="v_position_streetinfo" select="position()" />
<xsl:variable name="v_streetcode">
<xsl:value-of select="attr[@name='streetcode'])"/>
</xsl:variable>
<xsl:variable name="v_streetintake" select="attrQualMany[@name = 'streetintake']/value" />
<xsl:variable name="v_streetsizeDescription" select="attrQualMany[@name = 'streetsizeDescription']/value" />
<xsl:variable name="v_streetDetails" select="attrGroupMany[@name = 'streetDetails']/row" />
<xsl:for-each select="$v_streetintake">
<xsl:variable name="v_streetintakevalue" select="." />
<xsl:variable name="v_streetintakequal" select="./@qual" />
<xsl:for-each select="$v_streetsizeDescription">
<xsl:variable name="v_streetsizeDescriptionvalue" select="." />
<xsl:variable name="v_streetsizeDescriptionqual" select="./@qual" />
<xsl:for-each select="$v_streetDetails">
<xsl:variable name="v_streetTypeCode">
<xsl:value-of select="attr[@name='streetTypeCode'])"/>
</xsl:variable>
<xsl:variable name="v_streetContained" select="attrQualMany[@name = 'streetContained']/value" />
<xsl:for-each select="$v_streetContained">
<xsl:variable name="v_streetContainedvalue" select="." />
<xsl:variable name="v_streetContainedqual" select="./@qual" />
<RelatedObjectId>
<xsl:attribute name="referenceKey">
<xsl:value-of select="concat('ObjectId_Street','-',$v_position_streetinfo,'-',$v_streetcode,'-',$v_streetintakevalue,'-',$v_streetintakequal,'-',$v_streetsizeDescriptionvalue,'-',$v_streetsizeDescriptionqual,'-',$v_streetTypeCode,'-',$v_streetContainedvalue,'-',$v_streetContainedqual)"/>
</xsl:attribute>
</RelatedObjectId>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</xsl:for-each>
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
</xsl:template>
</xsl:stylesheet>
但是当任何一个可选循环都没有出现时,它就不起作用了。当所有可选循环都存在时,我已经编写了 XSLT,当消息中出现可选组的任何 1 或 2 或 3 或 none 时,我如何编写 XSLT。请建议
预期输出
当第一个可选组不存在时,输出将有8条记录。
<?xml version="1.0" encoding="UTF-8"?>
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz1-en-FAMS-5-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en-sz2-hi-FAMS-5-OZA" />
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
当第一个和第二个可选组不存在时,输出将有4条记录。
<?xml version="1.0" encoding="UTF-8"?>
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAT-2-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAT-3-OZA" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAMS-4-ONZ" />
<RelatedObjectId referenceKey="ObjectId_Street-1-AS_DRAINED--en--en-FAMS-5-OZA" />
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
好的。我不确定我是否完全理解您的预期输出。您的示例列出了 4 个可选循环,而不是两个,而且我不确定示例输出中缺少组的 "en" 来自哪里。
但是,这可以帮助您入门。我没有尝试在嵌套 for-each 结构中汇总所有内容,而是在类似于递归下降解析器的结构中使用多个模板。在每个级别,代码都会检查可选元素并在它们周围循环或跳到下一个级别。 referenceKey-strings 作为参数传递并在我们向下构建时构建。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/document">
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<xsl:for-each select="ObjectId/dlex/attrGroupMany[@name='streetinfo']">
<xsl:variable name="pos" select="position()"/>
<xsl:apply-templates select="row" mode="streetintake">
<xsl:with-param name="referenceKey" select="concat('ObjectId_Street-',$pos)" />
</xsl:apply-templates>
</xsl:for-each>
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
</xsl:template>
<xsl:template match="row" mode="streetintake">
<xsl:param name="referenceKey" />
<xsl:variable name="streetcode" select="concat($referenceKey,'-',attr[@name='streetcode'],'-')"/>
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetintake']/value">
<xsl:for-each select="attrQualMany[@name='streetintake']/value">
<xsl:apply-templates select="../.." mode="streetsize">
<xsl:with-param name="referenceKey" select="concat($streetcode,text(),'-',@qual)" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="streetsize">
<xsl:with-param name="referenceKey" select="$streetcode" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="streetsize">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetsizeDescription']/value">
<xsl:for-each select="attrQualMany[@name='streetsizeDescription']/value">
<xsl:apply-templates select="../../attrGroupMany[@name='streetDetails']" mode="streetdetails">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="attrGroupMany[@name='streetDetails']" mode="streetdetails">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="attrGroupMany" mode="streetdetails">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="row">
<xsl:apply-templates select="row" mode="streetdetails">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',row/attr[@name='streetTypeCode'])" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="streetdetails">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetContained']">
<xsl:apply-templates select="attrQualMany[@name='streetContained']">
<xsl:with-param name="referenceKey" select="$referenceKey"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="attrQualMany[@name='streetContained']">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="value">
<xsl:for-each select="value">
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" />
</xsl:call-template>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="RelatedObjectId">
<xsl:param name="referenceKey" />
<RelatedObjectId>
<xsl:attribute name="referenceKey"><xsl:value-of select="$referenceKey"/></xsl:attribute>
</RelatedObjectId>
</xsl:template>
</xsl:stylesheet>
我在现有代码中添加了更多片段,以处理所有可选组都缺失或完整
时的空情况 <attrGroupMany name="streetDetails"> details are missing.
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/document">
<CatalogObjectId>
<RelationshipData>
<Relationship>
<RelationType>ObjectId_Street</RelationType>
<RelatedObjectIds>
<xsl:for-each select="ObjectId/dlex/attrGroupMany[@name='streetinfo']">
<xsl:variable name="pos" select="position()"/>
<xsl:apply-templates select="row" mode="streetintake">
<xsl:with-param name="referenceKey" select="concat('ObjectId_Street-',$pos)" />
</xsl:apply-templates>
</xsl:for-each>
</RelatedObjectIds>
</Relationship>
</RelationshipData>
</CatalogObjectId>
</xsl:template>
<xsl:template match="row" mode="streetintake">
<xsl:param name="referenceKey" />
<xsl:variable name="streetcode" select="concat($referenceKey,'-',attr[@name='streetcode'],'-')"/>
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetintake']/value">
<xsl:for-each select="attrQualMany[@name='streetintake']/value">
<xsl:apply-templates select="../.." mode="streetsize">
<xsl:with-param name="referenceKey" select="concat($streetcode,text(),'-',@qual)" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="streetsize">
<xsl:with-param name="referenceKey" select="$streetcode" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="streetsize">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetsizeDescription']/value">
<xsl:choose>
<xsl:when test="attrGroupMany[@name='streetDetails']">
<xsl:for-each select="attrQualMany[@name='streetsizeDescription']/value">
<xsl:apply-templates select="../../attrGroupMany[@name='streetDetails']" mode="streetdetails">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" />
</xsl:apply-templates>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:for-each select="attrQualMany[@name='streetsizeDescription']/value">
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" />
</xsl:call-template>
</xsl:for-each>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:if test="not(attrQualMany[@name='streetintake']) and not(attrQualMany[@name='streetsizeDescription']) and not(attrGroupMany[@name='streetDetails'])">
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:if>
<xsl:apply-templates select="attrGroupMany[@name='streetDetails']" mode="streetdetails">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="attrGroupMany" mode="streetdetails">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="row">
<xsl:apply-templates select="row" mode="streetdetails">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',row/attr[@name='streetTypeCode'])" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="row" mode="streetdetails">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="attrQualMany[@name='streetContained']">
<xsl:apply-templates select="attrQualMany[@name='streetContained']">
<xsl:with-param name="referenceKey" select="$referenceKey"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="attrQualMany[@name='streetContained']">
<xsl:param name="referenceKey" />
<xsl:choose>
<xsl:when test="value">
<xsl:for-each select="value">
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="concat($referenceKey,'-',text(),'-',@qual)" />
</xsl:call-template>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="RelatedObjectId">
<xsl:with-param name="referenceKey" select="$referenceKey" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="RelatedObjectId">
<xsl:param name="referenceKey" />
<RelatedObjectId>
<xsl:attribute name="referenceKey">
<xsl:value-of select="$referenceKey"/>
</xsl:attribute>
</RelatedObjectId>
</xsl:template>