2

i have this XML:

<AAA>
    <BBB>
        <CCC>
            <DDD/>
        </CCC>
        <CCC>
            <EEE/>
        </CCC>
    </BBB>
    <BBB>
        <CCC>
            <EEE/>
        </CCC>
        <CCC>
            <DDD/>
        </CCC>
    </BBB>
    <BBB>
        <CCC>
            <EEE/>
        </CCC>
        <CCC>
            <EEE/>
        </CCC>
    </BBB>
    <BBB>
        <CCC>
            <DDD/>
        </CCC>
        <CCC>
            <EEE/>
        </CCC>
    </BBB>
</AAA>

And i want this result using a XSLT file:

<AAA>
   <XXX case="1" />
   <XXX case="2" />
   <XXX case="3" />
   <XXX case="1" />
</AAA>

Case 1: CCC[1] has DDD & CCC[2] has EEE
Case 2: CCC[1] has EEE & CCC[2] has DDD
Case 3: CCC[1] has EEE & CCC[2] has EEE

CCC always has only one item

I use the lxml Library in Python. I already got a XPath that matches case="1" in Notepad++:

//BBB/CCC[1]/DDD/../../CCC[2]/EEE

But if i try to use

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

    <xsl:template match="BBB/CCC[1]/DDD/../../CCC[2]/EEE">
      <XXX case="1" />
    </xsl:template>

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

</xsl:stylesheet>

I get this Error:

Traceback (most recent call last):
  File "C:/.../xsltest.py", line 11, in <module>
    transform_01 = etree.XSLT(xslt_01)
  File "xslt.pxi", line 412, in lxml.etree.XSLT.__init__ (src\lxml\lxml.etree.c:152223)
lxml.etree.XSLTParseError: Cannot parse stylesheet

If i only use BBB/CCC[1]/DDD the match works but it does not with the "..". How can i get the parent? Or is there another solution to my problem?

Waldi

W4ldi
  • 644
  • 5
  • 11
  • With what logic are you relating your input to your output? What are case 1, 2, 3, and 1? Can you please explain. – Lingamurthy CS Nov 26 '14 at 09:48
  • @LingamurthyCS i edited it, hope it is clear now – W4ldi Nov 26 '14 at 09:54
  • My bad, I don't understand it, still.. Can you try explaining it using sentences.. BTW, your template match, `BBB/CCC[1]/DDD/../../CCC[2]/EEE` is wrong, the axis in match pattern can have child axis or attribute axis.. you should try `BBB/CCC[2]/EEE` instead – Lingamurthy CS Nov 26 '14 at 09:59
  • @LingamurthyCS if the 1. CCC element in a BBB has a DDD and the 2. CCC element has a EEE element -> case 1. if the 1. CCC element of a BBB element has a EEE and the 2. CCC element has a DDD -> case 2. if both CCC have a EEE element -> case 3. – W4ldi Nov 26 '14 at 10:07
  • Please add the transform.error_log details when quoting Exceptions in \lxml\xslt.pxi. [errors-and-messages](https://lxml.de/xpathxslt.html#errors-and-messages) – dank8 Feb 20 '23 at 14:12

1 Answers1

0

Use this XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="BBB">
    <xsl:choose>
        <xsl:when test="CCC[1]/DDD and CCC[2]/EEE">
            <XXX case="1"/>
        </xsl:when>
        <xsl:when test="CCC[1]/EEE and CCC[2]/DDD">
            <XXX case="2"/>
        </xsl:when>
        <xsl:when test="CCC[1]/EEE and CCC[2]/EEE">
            <XXX case="3"/>
        </xsl:when>
    </xsl:choose>
</xsl:template>
<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
</xsl:template>
</xsl:stylesheet>
Lingamurthy CS
  • 5,412
  • 2
  • 13
  • 21