简体   繁体   中英

XSLT assign variable value from XML

From an XML document:

<samlp:Response ID="_f9daea33-e32a-4dde-beb4-d5227690b1a3" Version="2.0"
    IssueInstant="2015-07-30T15:06:58.874Z"
    Destination="https://domain.net/Login/PAuthentication.aspx?configSet=SAML"
    xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
        >urn:jh:identityprovider</saml:Issuer>
    <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
        <SignedInfo>
            <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
            <Reference URI="#_f9daea33-e32a-4dde-beb4-d5227690b1a3">
                <Transforms>
                    <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
                    <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                        <InclusiveNamespaces PrefixList="#default samlp saml ds xs xsi"
                            xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" />
                    </Transform>
                </Transforms>
                <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
                <DigestValue>uL1LoegsT53UGJE/HQqG9VW1Mnc=</DigestValue>
            </Reference>
        </SignedInfo>
        <SignatureValue>ifdW4P9/</SignatureValue>
        <KeyInfo>
            <X509Data>
                <X509Certificate>MIIHwzCCBaugAwIBAgIKeH+</X509Certificate>
            </X509Data>
        </KeyInfo>
    </Signature>
    <samlp:Status>
        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
    </samlp:Status>
    <saml:Assertion Version="2.0" ID="_b54ca592-4401-4107-a426-281918091842"
        IssueInstant="2015-07-30T15:06:58.898Z" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">
        <saml:Issuer>urn:jh:identityprovider</saml:Issuer>
        <saml:Subject>
            <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
                >ZQA|brandtest</saml:NameID>
            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml:SubjectConfirmationData NotOnOrAfter="2015-07-30T16:06:59.331Z"
                    Recipient="https://jacksonhewitt.brandmuscle.net/Login/PAuthentication.aspx?configSet=SAML"
                 />
            </saml:SubjectConfirmation>
        </saml:Subject>
        <saml:Conditions NotBefore="2015-07-30T14:06:59.331Z"
            NotOnOrAfter="2015-07-30T16:06:59.331Z">
            <saml:AudienceRestriction>
                <saml:Audience>https://domain.net/Login/PAuthentication.aspx?configSet=SAML</saml:Audience>
                <saml:Audience>https://domain.net/</saml:Audience>
            </saml:AudienceRestriction>
        </saml:Conditions>
        <saml:AttributeStatement>
            <saml:Attribute Name="Phone"
                NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
                <saml:AttributeValue>867-5309</saml:AttributeValue>
            </saml:Attribute>
        </saml:AttributeStatement>
        <saml:AttributeStatement>
            <saml:Attribute Name="Phone2"
                NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
                <saml:AttributeValue>555-1212</saml:AttributeValue>
            </saml:Attribute>
        </saml:AttributeStatement>
        <saml:AuthnStatement AuthnInstant="2015-07-30T15:06:59.335Z">
            <saml:AuthnContext>
                <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
            </saml:AuthnContext>
        </saml:AuthnStatement>
    </saml:Assertion>
</samlp:Response>

XSLT Document:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
        xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<xsl:template match="/">
    <AUTHENTICATOR>
        <USERINFO>
            <xsl:for-each select="/samlp:Response/*[local-name() = 'Assertion']/*[local-name() = 'AttributeStatement']/*">

            <!--This one works -->  
            <xsl:if test="(@Name='Phone')">
                <xsl:variable name="phone" select="*[local-name() = 'AttributeValue']" />
                <xsl:value-of select="$phone"/>
            </xsl:if>

            <!--This one doesn't work -->
            <xsl:variable name="phone2" select="samlp:AttributeValue[../@Name = 'Phone2']" />
            <xsl:value-of select="$phone2"/>

            </xsl:for-each>

            </USERINFO>
        </AUTHENTICATOR>
    </xsl:template>
</xsl:stylesheet>

When trying to output the value of the variable, it is empty. I'm guessing my 'select' syntax in the xsl:variable is incorrect?

I am able to get it to work like using the code below, but I don't want to have to use the 'if'.

    <xsl:if test="(@Name='Phone')">
       <xsl:variable name="phone" select="*[local-name() = 'AttributeValue']" />
       <xsl:value-of select="$phone"/>
    </xsl:if>

The key issue here is what the focus is. While the answer of proycon shows that you have used the attribute axis (with @ ), to access an element node, and that you forgot to use the namespace prefix, if you do not get the value, the focus may not be on saml:Attribute . Without seeing the rest of the code, it is hard to tell where it goes wrong.

Suppose you have this:

<xsl:template match="Attribute">
   <!-- your variable here -->

then the template would never be matched, because it is not in the correct namespace. But even if you fix this to be match="saml:Attribute" , your variable starts with * , which is short for child::* , and there is no child with an attribute Name under saml:Attribute .

Suppose you have this:

<xsl:template match="saml:Xyz">
   <!-- your variable here -->

then your focus is on some other node Xyz .

To fix it, you need the surrounding focus-setting expression ( xsl:template or xsl:for-each ) to select the parent of saml:Attribute , or you need to address the expression itself if the focus is something else. The following would work, depending on the rest of your stylesheet (ie, whether or not you applied templates to this node or not, here shown as a shallow-skip pattern):

Only outputs the phone number(s):

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

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

    <xsl:template match="saml:Attribute[@Name = 'Phone']">
        <xsl:variable name="phone" select="saml:AttributeValue" />
        <xsl:value-of select="$phone" />
    </xsl:template>

</xsl:stylesheet>

Update (after your Q. update)

While I typed my answer, you said you did not want to use xsl:if and that you got it to work with the following code:

<xsl:if test="(@Name='Phone')">
   <xsl:variable name="phone" select="*[local-name() = 'AttributeValue']" />
   <xsl:value-of select="$phone"/>
</xsl:if>

A few points of interest:

  1. Unless there is no way around it, do not use local-name() , if a direct NameTest suffices, in this case saml:AttributeValue (don't forget to add the namespace to the xsl:stylesheet root element)
  2. The parentheses in the xsl:if/@test are redundant
  3. You are right, you do not need xsl:if . You can simply change your variable to point to saml:AttributeValue[../@Name='Phone'] , which will select nothingness, unless its parent has Phone in the Name attribute. 0. In other words, this is the same:

     <xsl:variable name="phone" select="saml:AttributeValue[../@Name = 'Phone']" /> 

尽管AttributeValue名称具有误导性,但它是一个元素,而不是属性;)因此,请使用*[@Name='Phone']/saml:AttributeValue

If for any reason you don't want to use prefixes and don't want to use if , you can use the following:

        <xsl:variable name="phone" select="*[@Name='Phone']/*[local-name() = 'AttributeValue']" />
        <xsl:value-of select="$phone"/>

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