XSLT объединяет узел, когда значение атрибута отличается - PullRequest
2 голосов
/ 22 марта 2011

Во время трансформации я могу объединить один узел в другой. например, когда Attributes / Attribute / Type = ComplexAttr тогда он должен идти только под Attributes / Attribute / Type = Common. Ниже приведен пример XML & XSLT, который я пытаюсь использовать, но он не работает. TIA (заранее спасибо)

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="type" match="Attribute" use="Type"/>
    <xsl:template match="/">
        <Data Schema="XML A">
            <xsl:apply-templates select="XML/Attributes/Attribute">
                <xsl:sort select="Type" order="descending"/>
            </xsl:apply-templates>
            <errorCodes>
                <xsl:apply-templates select="XML/Attributes/Attribute"
                                     mode="errors"/>
            </errorCodes>
        </Data>
    </xsl:template>
    <xsl:template
            match="Attribute[generate-id()=generate-id(key('type', Type)[1])]">
        <xsl:if test="Type != 'ComplexAttr'">
            <Attributes type="{Type}">
                <xsl:if test="Type = 'ComplexAttr'">
                    <xsl:value-of select="Common"/>
                </xsl:if>
                <xsl:apply-templates select="../Attribute[Type=current()/Type]" mode="out"/>
            </Attributes>           
        </xsl:if>
    </xsl:template>
    <xsl:template match="Attribute" mode="out">
        <Attr id="{id}" name="{Name}" value="{Value}"/>
    </xsl:template>
    <xsl:template match="Attribute"/>
    <xsl:template match="Attribute" mode="errors"/>
    <xsl:template match="Attribute[Value='']" mode="errors">
        <errorCode>"value for <xsl:value-of select="Name"/> is missing."</errorCode>
    </xsl:template>
    <xsl:template match="/Attribute">
        <xsl:if test="Type = 'ComplexAttr'">
            <Attributes type="Common">
                <xsl:apply-templates select="../Attribute[Type=current()/Type]" mode="out"/>
                <!--<Attr id="{id}" name="{Name}" value="{Value}"/>-->
            </Attributes>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

---- Исходный XML ----

<?xml version="1.0" encoding="windows-1252"?>
<XML>
    <Attributes>
        <Attribute>
            <id>5</id>
            <Name>Buyer ID</Name>
            <Type>common</Type>
            <Value>Lee</Value>
        </Attribute>
        <Attribute>
            <id>331</id>
            <Name>Enviornment</Name>
            <Type>common</Type>
            <Value>Development</Value>
        </Attribute>
        <Attribute>
            <id>79</id>
            <Name>Retail</Name>
            <Type>common</Type>
            <Value></Value>
        </Attribute>
        <Attribute>
            <id>402</id>
            <Name>Gender</Name>
            <Type>category</Type>
            <Value>Men</Value>
        </Attribute>
    <Attribute>
         <id>1197</id> 
         <Name>UPC</Name> 
         <Type>ComplexAttr</Type> 
         <Value>Testing</Value> 
         <Path /> 
    </Attribute>
    </Attributes>
</XML>

---- Преобразованный вывод XML

<?xml version="1.0" encoding="utf-8"?>
<Data Schema="XML A">
  <Attributes type="common">
    <Attr id="5" name="Buyer ID" value="Lee" />
    <Attr id="331" name="Enviornment" value="Development" />
    <Attr id="79" name="Retail" value="" />
    <Attr id="41" name="PlusShip" value="False" />
    <Collection id="" name="test">
      <ComplexAttr refId="0">
        <MaskValue />
        <Attr id="1197" name="UPC" value="Testing" />
      </ComplexAttr>
    </Collection>
  </Attributes>
  <Attributes type="category">
    <Attr id="402" name="Gender" value="Men" />
    <Attr id="433" name="HeelHeight" value="" />
  </Attributes>
  <errorCodes>
    <errorCode>"value for Retail is missing."</errorCode>
  </errorCodes>
</Data>

1 Ответ

4 голосов
/ 22 марта 2011

Если вы хотите сгруппировать Attribute по Type с 'common' и 'ComplexAttr' в одной группе, вам нужно изменить выражение значения ключа на что-то вроде:

<xsl:key name="type" 
         match="Attribute" 
         use="concat(
                 Type[. != 'ComplexAttr'],
                 substring(
                    'common',
                    1 div (Type = 'ComplexAttr')
                 )
              )"/> 

<xsl:template match="Attribute[
                        generate-id()
                         = generate-id(
                              key('type',
                                  concat(
                                     Type[. != 'ComplexAttr'],
                                     substring(
                                        'common',
                                        1 div (Type = 'ComplexAttr')
                                     )
                                  )
                              )[1]
                           )
                     ]">       

РЕДАКТИРОВАТЬ : И в шаблонах групп применяются:

<xsl:apply-templates select="key('type',
                                 concat(
                                    Type[. != 'ComplexAttr'],
                                    substring(
                                       'common',
                                       1 div (Type = 'ComplexAttr')
                                    )
                                 )
                             )" 
                     mode="out"/> 

РЕДАКТИРОВАТЬ : Полный пример. Эта таблица стилей:

<!DOCTYPE xsl:stylesheet [
<!ENTITY key "concat(Type[. != 'ComplexAttr'],substring('common',1 div (Type = 'ComplexAttr')))">
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="type" match="Attribute" use="&key;"/>
    <xsl:template match="/">
        <Data Schema="XML A">
            <xsl:apply-templates
                 select="XML/Attributes/Attribute[
                            generate-id() = generate-id(key('type', &key;)[1])
                         ]">
                <xsl:sort select="&key;" order="descending"/>
            </xsl:apply-templates>
            <errorCodes>
                <xsl:apply-templates select="XML/Attributes/Attribute"
                                     mode="errors"/>
            </errorCodes>
        </Data>
    </xsl:template>
    <xsl:template match="Attribute">
        <xsl:variable name="vCurrent-Grouping-Key" select="&key;"/>
        <Attributes type="{$vCurrent-Grouping-Key}">
            <xsl:apply-templates select="key('type',$vCurrent-Grouping-Key)"
                                 mode="out"/>
        </Attributes>
    </xsl:template>
    <xsl:template match="Attribute" mode="out" name="makeAttr">
        <Attr id="{id}" name="{Name}" value="{Value}"/>
    </xsl:template>
    <xsl:template match="Attribute[Type='ComplexAttr']" mode="out">
        <Collection id="" name="test">
            <ComplexAttr refId="0">
                <MaskValue />
                <xsl:call-template name="makeAttr"/>
            </ComplexAttr>
        </Collection>
    </xsl:template>
    <xsl:template match="Attribute" mode="errors"/>
    <xsl:template match="Attribute[Value='']" mode="errors">
        <errorCode>"value for <xsl:value-of select="Name"/> is missing."</errorCode>
    </xsl:template>
</xsl:stylesheet>

Выход:

<Data Schema="XML A">
    <Attributes type="common">
        <Attr id="5" name="Buyer ID" value="Lee" />
        <Attr id="331" name="Enviornment" value="Development" />
        <Attr id="79" name="Retail" value="" />
        <Collection id="" name="test">
            <ComplexAttr refId="0">
                <MaskValue />
                <Attr id="1197" name="UPC" value="Testing" />
            </ComplexAttr>
        </Collection>
    </Attributes>
    <Attributes type="category">
        <Attr id="402" name="Gender" value="Men" />
    </Attributes>
    <errorCodes>
        <errorCode>"value for Retail is missing."</errorCode>
    </errorCodes>
</Data>
...