XSLT to select attribute from one element and use it to select value in another element

StackOverflow https://stackoverflow.com/questions/23676702

  •  23-07-2023
  •  | 
  •  

문제

so i want to find the id attribute which matches the sex attribute with a value of "m" or "f" and then use that id to select text from another element, i don't want to select text when sex="u".

thanks in advance!

here is sample xml:

<header>
            <personDesc>
                <person id="1234" sex="m"></person>
                <person id="3456" sex="f"></person>
                <person id="7890" sex="u"></person>
            </personDesc>
 </header>
 <stext>
            <u who="1234">
                <s>
                <w>Stuff I want</w>
                <w>to select</w>
                </s>    
            </u>
            <u who="3456">
                <s>
                <w>Stuff I want</w>  
                <w>to select</w>
                </s>
            </u>
            <u who="7890">
                <s>
                <w>stuff i don’t want</w>
                <w>to select</w>
                </s>
            </u>
 </stext>

i am trying to hack an existing script but am only getting the first w element:

<xsl:key name="uTab" match="u" use="@who"/>
<xsl:template match="/">
    <xsl:apply-templates select="//stext" />
 </xsl:template>
<xsl:template match="stext">
<xsl:for-each select=“../Header/particDesc/person">

<xsl:variable name="who">
   <xsl:value-of select="id"/>
</xsl:variable>
<td><xsl:value-of select="key('uTab',$who)//w"/></td>

</xsl:for-each>
</xsl:template>

i want output to show values for sex="m" or sex="f":

id 1234 stuff i want to select 
id 3456 stuff i want to select

hope this makes sense!

도움이 되었습니까?

해결책

After making the XML valid it might look like this:

<xml>
  <header>
    <personDesc>
      <person id="1234" sex="m" />
      <person id="3456" sex="f" />
      <person id="7890" sex="u" />
    </personDesc>
  </header>
  <stext>
    <u who="1234">
      <s>
        <w>Stuff I want</w>
        <w>to select</w>
      </s>
    </u>
    <u who="3456">
      <s>
        <w>Stuff I want</w>
        <w>to select</w>
      </s>
    </u>
    <u who="7890">
      <s>
        <w>stuff i don’t want</w>
        <w>to select</w>
      </s>
    </u>
  </stext>
</xml>

The XPath you might want to use in your XSL transformation is

/xml/stext/u[@who=/xml/header/personDesc/person[@sex!='u']/@id]/s

It means:

  • give me all nodes /xml/stext/u/s
  • which have the u/@who attribute set to ...
  • the person/@id attribute which ...
  • is on persons having @sex attribute not equal to u

The transformation could look like this:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xml:space="default" exclude-result-prefixes="" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text" omit-xml-declaration="no" indent="yes" />
  <xsl:template match="/xml/stext/u[@who=/xml/header/personDesc/person[@sex!='u']/@id]">
     id <xsl:value-of select="@who" />&#160;<xsl:for-each select=".//text()"><xsl:value-of select="." />&#160;</xsl:for-each></xsl:template>
  <xsl:template match="text()">
  </xsl:template>
</xsl:stylesheet>

다른 팁

By definition the value-of a node set (in XSLT 1.0) is the value of the first node in the set in document order. The key function is selecting all the matching elements but the value-of throws most of them away.

You will need to process all the nodes that key('uTab',$who)//w gives you (with for-each or apply-templates) and output the value of each one in turn.

I have written script for this. Have a look, this will help you. I just added before and after your xml you can remove it.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
  <xsl:template match="/">
      <xsl:for-each select="xml/header/personDesc/*">
          <xsl:if test="@sex!='u'">
              <xsl:variable name="selectedId" select="@id"/>
              <xsl:for-each select="/xml/stext/*">
                  <xsl:if test="$selectedId=@who">
                      <xsl:for-each select="s/w">
                          <xsl:element name="id">
                            <xsl:value-of select="$selectedId"/>  
                          </xsl:element>
                          <xsl:element name="w">
                            <xsl:value-of select="."/>
                          </xsl:element>
                      </xsl:for-each>
                  </xsl:if>
              </xsl:for-each>
          </xsl:if>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

output is :

<?xml version="1.0" encoding="UTF-8"?>
<transformiix:result xmlns:transformiix="http://www.mozilla.org/TransforMiix">
    <id>1234</id>
    <w>Stuff I want</w>
    <id>1234</id>
    <w>to select</w>
    <id>3456</id>
    <w>Stuff I want</w>
    <id>3456</id>
    <w>to select</w>
</transformiix:result>

mark it up if it helps and works.

Thanks,
Gaurav

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top