문제

My input XML has the following structure:

<catalog>
<cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <company>Columbia</company>
    <price>10.90</price>
    <year>1985</year>
    <attributes>
        <attribute>
            <key>1</key>
            <value>one</value>
        </attribute>
        <attribute>
            <key>2</key>
            <value>two</value>
        </attribute>
    </attributes>
</cd>
<cd>
    <title>Hide your heart</title>
    <artist>Bonnie Tyler</artist>
    <country>UK</country>
    <company>CBS Records</company>
    <price>9.90</price>
    <year>1988</year>
    <attributes>
        <attribute>
            <key>1</key>
            <value>one</value>
        </attribute>
        <attribute>
            <key>2</key>
            <value>two</value>
        </attribute>
    </attributes>
</cd>
<cd>
    <title>Greatest Hits</title>
    <artist>Dolly Parton</artist>
    <country>USA</country>
    <company>RCA</company>
    <price>9.90</price>
    <year>1982</year>
    <attributes>
        <attribute>
            <key>1</key>
            <value>one</value>
        </attribute>
        <attribute>
            <key>2</key>
            <value>two</value>
        </attribute>
    </attributes>
</cd>
<cd>
    <title>Still got the blues</title>
    <artist>Gary Moore</artist>
    <country>UK</country>
    <company>Virgin records</company>
    <price>10.20</price>
    <year>1990</year>
    <attributes>
        <attribute>
            <key>1</key>
            <value>WON</value>
        </attribute>
        <attribute>
            <key>2</key>
            <value>two</value>
        </attribute>
    </attributes>
</cd>   
</catalog>

Now, I am trying to create a different xml by selecting only those cd nodes for which { key = 1 and value = WON } (Value node which is sibling of that key node). Been stuck on this for a while, trying to apply multiple conditions. Tried following approaches: 1. Try to copy those nodes that match conditions 2. Doing an identity copy & ignoring those nodes that do not match condition

Not sure if this is feasible, or I am doing something wrong. Here is what my xslt looks like:

<?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:variable name="KeyToBeMatched">1</xsl:variable>
<xsl:param name="ValueToBeMatched">WON</xsl:param>


<xsl:template match="catalog">

      <xsl:for-each select="cd">
        <xsl:for-each select="attributes/attribute[keu = $KeyToBeMatched]">
            <xsl:variable name="attributeValue" select="value"/>
                <xsl:if test="$attributeValue = $RMGAccountId"> 
                        <xsl:copy>
                            <xsl:apply-templates select="@*|*|text()" />
                        </xsl:copy>
                </xsl:if>
        </xsl:for-each>
      </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Have tried other combinations too. Would really appreciate any help on this.

Thanks, Ani

도움이 되었습니까?

해결책

I am not sure if you want to copy the whole cd element or not should it have a matching attribute, but if you did, you could simply add a matching template like this, in which you then add code to copy the element

<xsl:template match="cd[attributes/attribute[key='1'][value='WON']]">
    <!-- Copy element -->
</xsl:template>

Other cd elements can then be matched and ignored

<xsl:template match="cd" />

Try this XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="cd[attributes/attribute[key='1'][value='WON']]">
      <xsl:call-template name="identity" />
   </xsl:template>

   <xsl:template match="cd" />

   <xsl:template match="@*|node()" name="identity">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

When applied to your sample XML, out the late, great Gary Moore is output

<catalog>
   <cd>
      <title>Still got the blues</title>
      <artist>Gary Moore</artist>
      <country>UK</country>
      <company>Virgin records</company>
      <price>10.20</price>
      <year>1990</year>
      <attributes>
         <attribute>
            <key>1</key>
            <value>WON</value>
         </attribute>
         <attribute>
            <key>2</key>
            <value>two</value>
         </attribute>
      </attributes>
   </cd>
</catalog>

Of course, in your case, you need to parameterise the matching values, in which case you can't use this approach, because variables can't be use in the template match. Instead, you could use a xsl:for-each to match the cd elements:

<xsl:for-each select="cd[attributes/attribute[key=$KeyToBeMatched][value=$ValueToBeMatched]]">

Here is the full XSLT for this approach

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="xml" indent="yes"/>

   <xsl:variable name="KeyToBeMatched">1</xsl:variable>
   <xsl:param name="ValueToBeMatched">WON</xsl:param>

   <xsl:template match="catalog">
      <xsl:for-each select="cd[attributes/attribute[key=$KeyToBeMatched][value=$ValueToBeMatched]]">
         <xsl:call-template name="identity"/>
      </xsl:for-each>
   </xsl:template>
   <xsl:template match="@*|node()" name="identity">
      <xsl:copy>
         <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
   </xsl:template>
</xsl:stylesheet>

This will also return the awesome Gary Moore.

다른 팁

try this one:

<?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:variable name="KeyToBeMatched">1</xsl:variable>
<xsl:param name="ValueToBeMatched">WON</xsl:param>

<xsl:template match="list"> 
    <xsl:for-each select="cd">
        <xsl:for-each select="attributes/attribute[key = $KeyToBeMatched]">
            <xsl:variable name="attributeValue" select="value"/>
            <xsl:if test="$attributeValue = $ValueToBeMatched"> 
                <xsl:copy>
                    <xsl:apply-templates select="@*|*|text()" />
                </xsl:copy>
            </xsl:if>
        </xsl:for-each>
    </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Variable "RMGAccountId" has never been declared, I exchanged that with "ValueToBeMatched". and also fixed the typo that Filype pointed out. Applied to the source you get this XML:

<?xml version="1.0" encoding="UTF-8"?>
<attribute> 1 WON </attribute>

Best regards, Peter

There's a typo on

--------------------------------------------V---------------------
<xsl:for-each select="attributes/attribute[keu = $KeyToBeMatched]">
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top