简体   繁体   中英

Creating the id (unique identifier) from paragraph content in XML using XSLT

I want to create an xsl for an identifier will be extracted from the part of StatementCode tag in provided input code

The input XML is:

<?xml version="1.0" encoding="UTF-8"?>
<LearningStandards>
    <StatementCodes>
        <StatementCode>AA.BBB-LA.K2.L.1</StatementCode>
    </StatementCodes>
    <Statements>
        <Statement>Demonstrate command of the conventions.</Statement>
    </Statements>
    <StatementCodes>
        <StatementCode>AADD.EPF-Caree.CSDA.L.4</StatementCode>
    </StatementCodes>
    <Statements>
        <Statement>Determine or clarify.</Statement>
    </Statements>
</LearningStandards>

The XSLT used is:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="LearningStandards">
        <topic id="x1" xml:lang="en-US" outputclass="CCSSI-DITA"><title/>
            <body>
                <xsl:apply-templates/>
            </body>
        </topic>
    </xsl:template>

    <xsl:template match="StatementCodes">
        <bodydiv outputclass="StatementCodes">
            <xsl:apply-templates/>
        </bodydiv>
    </xsl:template>

    <xsl:template match="StatementCode">
        <p outputclass="StatementCode">
            <xsl:apply-templates/>
        </p>
    </xsl:template>

    <xsl:template match="Statements">
        <bodydiv outputclass="Statements">
            <xsl:apply-templates/>
        </bodydiv>
    </xsl:template>

    <xsl:template match="Statement">
        <p outputclass="Statement">
            <xsl:apply-templates/>
        </p>
    </xsl:template>
</xsl:stylesheet>

The output XML is:

<?xml version="1.0" encoding="UTF-8"?>
<topic id="x1" xml:lang="en-US" outputclass="DITA">
    <title/>
    <body>
        <bodydiv outputclass="StatementCodes">
            <p outputclass="StatementCode">AA.BBB-LA.K2.**L.1**</p>
        </bodydiv>
        <bodydiv outputclass="Statements">
            <p outputclass="Statement">Demonstrate command of the conventions.</p>
        </bodydiv>
        <bodydiv outputclass="StatementCodes">
            <p outputclass="StatementCode">AADD.EPF-Caree.CSDA.L.4</p>
        </bodydiv>
        <bodydiv outputclass="Statements">
            <p outputclass="Statement">Determine or clarify.</p>
        </bodydiv>
    </body>
</topic>

And I need the output as follows:

<?xml version="1.0" encoding="UTF-8"?>
<topic id="x1" xml:lang="en-US" outputclass="DITA">
    <title/>
    <body>
        <bodydiv outputclass="StatementCodes">
            <p outputclass="StatementCode">AA.BBB-LA.K2.**L.1**</p>
        </bodydiv>
        <bodydiv outputclass="Statements">
            <p id="L.1" outputclass="Statement">Demonstrate command of the conventions.</p>    <!-- id="L.1" is the critical point -->
        </bodydiv>
        <bodydiv outputclass="StatementCodes">
            <p outputclass="StatementCode">AADD.EPF-Caree.CSDA.L.4</p>
        </bodydiv>
        <bodydiv outputclass="Statements">
            <p id="L.4" outputclass="Statement">Determine or clarify.</p>
        </bodydiv>
    </body>
</body>
</topic>

Please give me suggestions on this XSLT.

For a given Statement element, to get the relevant 'StatementCode` it looks like you need to do this...

<xsl:variable name="code" select="../preceding-sibling::StatementCodes[1]/StatementCode" />

To use this in an ID, you could use Attribute Value Templates

<p outputclass="Statement" id="{$code}">

Unfortunaly, you have failed explained the logic behind why you only a particular substring from the code. Perhaps you want to get only the portion for "L." onwards? If so, the expression would be this:

<p outputclass="Statement" id="L.{substring-after($code, '.L.')}">

Or, maybe you want everything after the third full stop. As you are using XSLT 2.0, you could do it like this:

<p id="{replace($code, '^\w+\.\w+-\w+\.\w+\.', '')}">

Also, in XSLT 2.0, if you wanted to get everything after the second-from-last full stop, you can use tokenize (together with string-join to re-join the tokens with a full-stop between them)

<p id="{string-join(tokenize($code, '\.')[position() >= last() - 1], '.')}">

Try this template, which shows all four methods in action

 <xsl:template match="Statement">
    <xsl:variable name="code" select="../preceding-sibling::StatementCodes[1]/StatementCode" />
    <p outputclass="Statement" 
          id="{$code}" 
          id1="L.{substring-after($code, '.L.')}" 
          id2="{replace($code, '^\w+\.\w+-\w+\.\w+\.', '')}"
          id3="{string-join(tokenize($code, '\.')[position() >= last() - 1], '.')}">
       <xsl:apply-templates/>
    </p>
 </xsl:template>

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