简体   繁体   中英

How to compare two xml attributes

currently it compares the <title> and do the manipulation and I wanted also to compare <code>&<title> Thanks

  <Types xmlns:p="foo">
   <Type>
    <title> TestingOne</title>
    <values>
        <attribute name="vala">10</attribute>
        <attribute name="codeCom">code1</attribute>
        <attribute name="valb">20</attribute>
        <attribute name="valc">30</attribute>
        <attribute name="vald">40</attribute>
    </values>
    <title> TestingTwo</title>
    <values>
        <attribute name="vala">10</attribute>
       <attribute name="codeCom">code2</attribute>
        <attribute name="valb">20</attribute>
        <attribute name="valc">15</attribute>
        <attribute name="vald">45</attribute>
    </values>
   </Type>
   <comparison>
    <comparisionList>
        <object>TestingOne</object>
        <condition>valc=30</condition>
        <code>Code1</code>
        <newName>vald</newName>
        <newValue>60</newValue>
    </comparisionList>
    <comparisionList>
        <object>TestingTwo</object>
        <condition>valb=40 or valb=20</condition>
        <code>Code2</code>
        <newName>vald</newName>
        <newValue>60</newValue>
    </comparisionList>
   </comparison>
  </Types>

XSL is here

                <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:str="http://exslt.org/strings">
            <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

            <xsl:template match="/*">
              <xsl:apply-templates select="Type"/>
            </xsl:template>

            <xsl:template match="Type">
             <OutPut>
               <xsl:apply-templates select="values"/>
             </OutPut>
            </xsl:template>

            <xsl:template match="values">
             <xsl:variable name="testName"  
              select="normalize-space(./preceding-sibling::title[1])"/>
             <xsl:variable name="testCode"  
              select="normalize-space(attribute[@name='code'])"/>
             <xsl:element name="{$testName}">
             <xsl:variable name="checkIfCondition">
              <xsl:apply-templates  select="./attribute" mode="attributeCheck">
               <xsl:with-param name="groupName" select="$testName"/>
               <xsl:with-param name="codeName" select="$testCode"/>
               <xsl:with-param name="toBeChecked" select="'shouldReplace'"/>
              </xsl:apply-templates>
             </xsl:variable>

             <xsl:variable name="checkConditionName">
               <xsl:apply-templates  select="./attribute" mode="attributeCheck">
                <xsl:with-param name="groupName" select="$testName"/>
                <xsl:with-param name="toBeChecked" select="'shouldReplaceName'"/>
               </xsl:apply-templates>
             </xsl:variable>

             <xsl:variable name="checkConditionValue">
               <xsl:apply-templates  select="./attribute" mode="attributeCheck">
                <xsl:with-param name="groupName" select="$testName"/>
                <xsl:with-param name="toBeChecked" select="'shouldReplaceValue'"/>
               </xsl:apply-templates>
             </xsl:variable>

             <xsl:choose>
               <xsl:when test="$checkIfCondition ='true'">
                  <xsl:apply-templates  select="./attribute" mode="attributeChange">
                     <xsl:with-param name="groupName" select="$testName"/>
                     <xsl:with-param name="changeName" select="$checkConditionName"/>
                     <xsl:with-param name="changeValue" select="$checkConditionValue"/>
                  </xsl:apply-templates>
               </xsl:when>
               <xsl:otherwise>
                  <xsl:apply-templates  select="./attribute" mode="attributes"/>
               </xsl:otherwise>
              </xsl:choose>
             </xsl:element>
            </xsl:template>

            <xsl:template match="attribute" mode="attributeCheck">
                <xsl:param name="groupName"/>
                <xsl:param name="codeName"/>
                <xsl:param name="toBeChecked" select="'default'"/>
                <xsl:variable name="attributeName" select="."/>

             <xsl:variable name="testComparisionList" 
                  select="//comparisionList
                            [normalize-space(object) = $groupName and normalize-space(code) = $codeName]"/>

             <xsl:variable name="testCondition" 
                  select="normalize-space($testComparisionList/condition)"/>

            <xsl:variable name="conditionNewName" 
               select="normalize-space(//comparisionList/object[normalize-space(.)
              =$groupName]/parent::*/newName)"/>
            <xsl:variable name="conditionNewValue" 
              select="normalize-space(//comparisionList/object[normalize-space(.)
             =$groupName]/parent::*/newValue)"/>
            <xsl:variable name="conditionRules" select="str:tokenize($testCondition,'or')"/>
            <xsl:for-each select="str:tokenize($testCondition,'or')">
              <xsl:variable name="conditionParams" 
                   select="str:tokenize(normalize-space(.),'=')"/>
              <xsl:variable name="conditionName" select="$conditionParams[1]"/>
              <xsl:variable name="conditionValue" select="$conditionParams[2]"/>

              <xsl:key name="compare" 
     match="comparisionList" 
     use="concat(normalize-space(object), '|', normalize-space(code))" />

     <xsl:variable name="testComparisionList" 
  select="key('compare', concat($groupName, '|', $codeName))"/>




              <xsl:choose>
                <xsl:when test="$attributeName/@name = $conditionName 
                          and $attributeName = $conditionValue">
                  <xsl:choose>
                     <xsl:when test="$toBeChecked='shouldReplace' ">
                       <xsl:text>true</xsl:text>
                     </xsl:when>
                     <xsl:when test="$toBeChecked='shouldReplaceName'">
                       <xsl:value-of select="$conditionNewName"/>
                     </xsl:when>
                     <xsl:when test="$toBeChecked='shouldReplaceValue'">
                       <xsl:value-of select="$conditionNewValue"/>
                     </xsl:when>
                     <xsl:otherwise></xsl:otherwise>
              </xsl:choose>
             </xsl:when>
             <xsl:otherwise></xsl:otherwise>
            </xsl:choose>
            </xsl:for-each>
            </xsl:template>

            <xsl:template match="attribute" mode="attributes">
            <xsl:param name="groupName"/>
            <xsl:variable name="testGroupName" select="$groupName"/>
            <xsl:value-of select="$testGroupName"/>
            <xsl:element name="{./@name}">
              <xsl:value-of select="."/>
            </xsl:element>
            </xsl:template>

            <xsl:template match="attribute" mode="attributeChange">
            <xsl:param name="groupName"/>
            <xsl:param name="changeName"/>
            <xsl:param name="changeValue"/>
            <xsl:choose>
              <xsl:when test="$changeName = ./@name">
                <xsl:element name="{./@name}">
                  <xsl:value-of select="$changeValue"/>
                </xsl:element>
              </xsl:when>
              <xsl:otherwise>
               <xsl:element name="{./@name}">
                <xsl:value-of select="."/>
               </xsl:element>
              </xsl:otherwise>
             </xsl:choose>
            </xsl:template>
            </xsl:stylesheet>

currently it compares the <title> and do the manipulation in the xslt and I wanted also to compare <code>&<title> . I was thinking something like select="normalize-space(./preceding-sibling::[title[1] and [code])"/> Thanks

It would have helped if you had included information on the "attribute" template because, crucially, there is currently where it compares the title element.

Looking at your previous question, which I am assuming this current question follows on from, the "attribute" template starts like this...

<xsl:template match="attribute" mode="attributeCheck">
    <xsl:param name="groupName"/>
    <xsl:param name="toBeChecked" select="'default'"/>

    <xsl:variable name="testGroupName" select="$groupName"/>

    <xsl:variable name="testCondition" 
          select="normalize-space(//comparisionList/object[normalize-space(.)
                    = $testGroupName]/parent::*/condition)"/>

It might help to re-write the testCondition variable, to get just the comparisionList element in to variable, which can then be re-used to get subsequent child elements.

 <xsl:variable name="testComparisionList" 
      select="//comparisionList[normalize-space(object) = $groupName]"/>

 <xsl:variable name="testCondition" 
      select="normalize-space($testComparisionList/condition)"/>

(Note, I have also dropped the slightly unnecessary testGroupName variable, as it was exactly the same as the groupName variable anyway)

So, what you need to do is pass in the code and add this to the xpath condition on comparisonList

<xsl:template match="attribute" mode="attributeCheck">
    <xsl:param name="groupName"/>
    <xsl:param name="codeName"/>
    <xsl:param name="toBeChecked" select="'default'"/>

 <xsl:variable name="testComparisionList" 
      select="//comparisionList
                [normalize-space(object) = $groupName and normalize-space(code) = $codeName]"/>

 <xsl:variable name="testCondition" 
      select="normalize-space($testComparisionList/condition)"/>

And to call the template, you would then do this

<xsl:template match="values">
 <xsl:variable name="testName"  
  select="normalize-space(./preceding-sibling::title[1])"/>
 <xsl:variable name="testCode"  
  select="normalize-space(attribute[@name='code'])"/>
 <xsl:element name="{$testName}">
 <xsl:variable name="checkIfCondition">
  <xsl:apply-templates  select="./attribute" mode="attributeCheck">
   <xsl:with-param name="groupName" select="$testName"/>
   <xsl:with-param name="codeName" select="$testCode"/>
   <xsl:with-param name="toBeChecked" select="'shouldReplace'"/>
  </xsl:apply-templates>
 </xsl:variable>

EDIT: A more efficient way to look-up comparisionList would be to define a key. To look them up using both title and element, you could define a key like so

<xsl:key name="compare" 
         match="comparisionList" 
         use="concat(normalize-space(object), '|', normalize-space(code))" />

Then the setting of the testComparisionList is like this:

 <xsl:variable name="testComparisionList" 
      select="key('compare', concat($groupName, '|', $codeName))"/>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM