juls_pro_37
juls_pro_37

Reputation: 79

No output of some tag XSLT 1.0

How can i output the value of NUMBER for every GRP/ADD/CONTACT where QUALIFIER = EM?

Correct output should be: [email protected]. Please find my XML and XSLT attached:

XML:

<?xml version="1.0"?>
<TEST>
  <CNT>
    <GRP>
      <ADD>
        <QUALIFIER>DP</QUALIFIER>
        <PARTY_NAME_1>Vorname Nachname</PARTY_NAME_1>
        <STREET_1>Strasse 1</STREET_1>
        <CITY>Ort</CITY>
        <POSTAL_CODE>12345</POSTAL_CODE>
        <COUNTRY_CODE>DE</COUNTRY_CODE>
        <CONTACT>
          <QUALIFIER>TE</QUALIFIER>
          <NUMBER>4657</NUMBER>
        </CONTACT>
        <CONTACT>
          <QUALIFIER>EM</QUALIFIER>
          <NUMBER>[email protected]</NUMBER>
        </CONTACT>
      </ADD>
      <ADD>
        <QUALIFIER>ST</QUALIFIER>
        <PARTY_NAME_1>Vorname Nachname</PARTY_NAME_1>
        <STREET_1>Strasse 1</STREET_1>
        <CITY>Ort</CITY>
        <POSTAL_CODE>12345</POSTAL_CODE>
        <COUNTRY_CODE>DE</COUNTRY_CODE>
        <CONTACT>
          <QUALIFIER>TE</QUALIFIER>
          <NUMBER>12345</NUMBER>
        </CONTACT>
        <CONTACT>
          <QUALIFIER>EM</QUALIFIER>
          <NUMBER>[email protected]</NUMBER>
        </CONTACT>
      </ADD>
    </GRP>
  </CNT>
</TEST>

XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
    <xsl:output method="xml" indent="yes"/>

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

    <xsl:template match="GRP">
      <xsl:copy>
        <xsl:for-each select ="./ADD/CONTACT[QUALIFIER='ST']">
          <xsl:if test="./QUALIFIER='EM'">
            <CONTACT_EMAIL>
              <xsl:value-of select="NUMBER"/>
            </CONTACT_EMAIL>
          </xsl:if>
        </xsl:for-each>
        <!--copy all other nodes -->
        <xsl:apply-templates select="@* | node()" />
      </xsl:copy>
    </xsl:template>

    <!-- delete empty nodes -->
    <xsl:template match="node()|@*">
      <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
      </xsl:copy>
    </xsl:template>
    <xsl:template match="*[not(@*|*|comment()|processing-instruction()) and normalize-space()='']"/>
    <!-- delete empty nodes -->
</xsl:stylesheet>

I also tried this:

<xsl:for-each select ="./ADD/CONTACT"> instead of <xsl:for-each select ="./ADD/CONTACT[QUALIFIER='ST']">, but there i get all data of the value "number" (from qualifier DP and ST) but i need just from qualifier ST.

Upvotes: 1

Views: 83

Answers (3)

michael.hor257k
michael.hor257k

Reputation: 117043

If that's the result you want, you could do simply:

<xsl:template match="GRP">
    <xsl:copy>
        <xsl:for-each select ="ADD[QUALIFIER='ST']/CONTACT[QUALIFIER='EM']">
            <CONTACT_EMAIL>
                <xsl:value-of select="NUMBER"/>
            </CONTACT_EMAIL>
        </xsl:for-each>
        <!--copy all other nodes -->
        <xsl:apply-templates/>
    </xsl:copy>
</xsl:template>

Upvotes: 1

juls_pro_37
juls_pro_37

Reputation: 79

<xsl:template match="GRP">
  <xsl:copy>
    <xsl:for-each select ="./ADD[QUALIFIER='ST']">
      <xsl:if test="./CONTACT/QUALIFIER='EM'">
        <CONTACT_EMAIL>
          <xsl:value-of select="CONTACT[QUALIFIER='EM']/NUMBER"/>
        </CONTACT_EMAIL>
      </xsl:if>
    </xsl:for-each>
    <!--copy all other nodes -->
    <xsl:apply-templates select="@* | node()" />
  </xsl:copy>
</xsl:template>

Result:

<TEST>
  <CNT>
      <GRP>
         <CONTACT_EMAIL>[email protected]</CONTACT_EMAIL>
         <ADD>
            <QUALIFIER>DP</QUALIFIER>
            <PARTY_NAME_1>Vorname Nachname</PARTY_NAME_1>
            <STREET_1>Strasse 1</STREET_1>
            <CITY>Ort</CITY>
            <POSTAL_CODE>12345</POSTAL_CODE>
            <COUNTRY_CODE>DE</COUNTRY_CODE>
            <CONTACT>
               <QUALIFIER>TE</QUALIFIER>
               <NUMBER>4657</NUMBER>
            </CONTACT>
            <CONTACT>
               <QUALIFIER>EM</QUALIFIER>
               <NUMBER>[email protected]</NUMBER>
            </CONTACT>
         </ADD>
         <ADD>
            <QUALIFIER>ST</QUALIFIER>
            <PARTY_NAME_1>Vorname Nachname</PARTY_NAME_1>
            <STREET_1>Strasse 1</STREET_1>
            <CITY>Ort</CITY>
            <POSTAL_CODE>12345</POSTAL_CODE>
            <COUNTRY_CODE>DE</COUNTRY_CODE>
            <CONTACT>
               <QUALIFIER>TE</QUALIFIER>
               <NUMBER>12345</NUMBER>
            </CONTACT>
            <CONTACT>
               <QUALIFIER>EM</QUALIFIER>
               <NUMBER>[email protected]</NUMBER>
            </CONTACT>
         </ADD>
      </GRP>
  </CNT>
</TEST>

Upvotes: 0

Tomalak
Tomalak

Reputation: 338288

You have the identity template (<xsl:template match="@* | node()">) twice in your XSLT, you can remove the second one.

That being said, your logic goes like this

<xsl:for-each select ="./ADD/CONTACT[QUALIFIER='ST']">
  <xsl:if test="./QUALIFIER='EM'">
    <CONTACT_EMAIL>
      <xsl:value-of select="NUMBER"/>
    </CONTACT_EMAIL>
  </xsl:if>
</xsl:for-each>

This cannot work. Judging from your example XML, there can't be a <CONTACT> with qualifier equal to ST that also has a qualifier equal to EM.

You probably mean this:

<xsl:for-each select ="ADD/CONTACT[QUALIFIER='EM']">
  <CONTACT_EMAIL>
    <xsl:value-of select="NUMBER"/>
  </CONTACT_EMAIL>
</xsl:for-each>

Notes

  • I'm not sure that your "copy all other nodes" call to <xsl:apply-templates select="@* | node()" /> is what you want. I'd say it's not.
  • Writing ./ is redundant in XPath. Every path that does not start at the root of the document is relative to the current node by default anyway.

Upvotes: 1

Related Questions