简体   繁体   中英

Why does this XSLT not generate my expected output?

I'm trying to transform an XML to another XML, using XSLT. Here's my XML

<?xml version="1.0" encoding = "iso-8859-1"?>
<Förskoleansökan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <?xml-stylesheet type="text/xsl" href="XSLTFile1.xslt"?>

  <Förskolenamn>Dalabergs förskola</Förskolenamn>

  <Barn>

    <Förnamn>Nils</Förnamn>
    <Efternamn>Petersson</Efternamn>
    <Personnummer>1008021245</Personnummer>


    <Syskon>
      <Personnummer>0005052464</Personnummer>
      <Förnamn>Johan</Förnamn>
      <Efternamn>Petersson</Efternamn>

    </Syskon>

    <Övrigt>

      <Allergier>Inga allergier</Allergier>
      <AnnatÖmmandeSkäl></AnnatÖmmandeSkäl>


    </Övrigt>

  </Barn>

  <Vårdnadshavare>

     <Vårdnadshavare1 personnummer="7806032356">
            <Förnamn>Mia</Förnamn>
            <Efternamn>Petersson</Efternamn>
    </Vårdnadshavare1>

    <Vårdnadshavare2 personnummer="7806089645">
            <Förnamn>Jörgen</Förnamn>
            <Efternamn>Petersson</Efternamn>
       
    </Vårdnadshavare2>

  </Vårdnadshavare>


</Förskoleansökan>

I'm trying to transform that XML to this one

<begaranominkomstuppgift>
    <person personnummer="7806032356">
      <fornamn>Mia</fornamn>
      <efternamn>Petersson</efternamn>
    </person>
    <person personnummer="7806089645">
      <fornamn>Jörgen</fornamn>
      <efternamn>Petersson</efternamn>
    </person>
</begaranominkomstuppgift>

Here's my XSL

    <?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <begaraninkomstuppgift>
      <xsl:for-each select="Förskoleansökan/Vårdnadshavare">
        <person>
          <xsl:attribute name="personummer">
            <xsl:value-of select="personnummer"/>
          </xsl:attribute>
          <fornamn>
            <xsl:value-of select="Vårdnadshavare/Förnamn" />
          </fornamn>
          <efternamn>
            <xsl:value-of select="Vårdnadshavare/Efternamn" />
          </efternamn>
        </person>
      </xsl:for-each>
    </begaraninkomstuppgift>
  </xsl:template>
</xsl:stylesheet>

The transformation doesn't occur and my output is still the old XML. What seems to be the issue here?

The XML is most certainly my work and basically i'm happy about the structure. I structured the way it's easiest for me. I would greatly appreciate it, if you could help me out here. I'm not expecting you to create a completely new stylesheet, but just point out the flaws in my current one.

The primary goal of Stackoverflow is to teach people what they need to know, not to give them what they want.

An XSLT transformation never exists on its own (exception: generic transformations like the identity transform), it only makes sense if it is related to a specific input XML document. The input is what you start with.

Sometimes, you will find yourself in a situation where the input is defined by someone else (your customer, an external provider, your boss wants it this way etc.) and you have to cope with it, no matter if the XML format is sensible or not.

But that's not the case for you, you are in charge of designing your own input document and choosing a good design will greatly simplify the task of creating an XSLT stylesheet to process the input (your ultimate goal).

Well i'm a beginner so that's why it looks really bad to you guys. The important thing is that the XML is well-formed and does not contain any errors.

No, not really. Well-formedness is a precondition for anything to be called XML in the first place, but it does not say anything about the usefulness of the design.


Now let's have a look at your design. First of all, the <?xml-stylesheet processing instruction should be at the beginning of the file, right after the XML declaration:

Next, looking at the contents of Barn :

<Barn>
    <Förnamn>Nils</Förnamn>
    <Efternamn>Petersson</Efternamn>
    <Personnummer>1008021245</Personnummer>
    <Syskon>
        <Personnummer>0005052464</Personnummer>
        <Förnamn>Johan</Förnamn>
        <Efternamn>Petersson</Efternamn>
    </Syskon>
    <Övrigt>
        <Allergier>Inga allergier</Allergier>
        <AnnatÖmmandeSkäl/>
    </Övrigt>
</Barn>

The three same elements occur as direct children of Barn and also inside Syskon , but the order is different, which does not make sense. The order of elements is significant in XML.

Above, the person number is represented as an element, but later in the document, the person number is stored as an attribute, which will certainly cause confusion.

Inside Vårdnadshavare , there are the child elements Vårdnadshavare1 and Vårdnadshavare2 . Element names should never be designed in this way because it complicates automatic processing (because each element name is unique) and because the number is actually the position of the element, which is obvious.

Things that are the same should have the same name, without a number. If you need the number in it, you could have an attribute like

<Vårdnadshavare n="1">

but, as I said, it is almost certainly superfluous.

Please note : On many aspects of the design I cannot comment because the element names are in a language I do not understand. And it is hard to propose an improved XML design because of this. If you plan to ask further XSLT questions, you might get better help if you translate the content.

why is it not working?

It is working - it's just not working the way you expect.

The main reason for this is that you create a person for each Förskoleansökan/Vårdnadshavare . There is only one Vårdnadshavare element in your XML, so only one person is created.

To get the two persons you want, you need to create a person for each child node of Vårdnadshavare . You have named these Vårdnadshavare1 and Vårdnadshavare2 , which makes it difficult to select them by name. If we assume that they are the only children of Vårdnadshavare , we could do:

<xsl:for-each select="Förskoleansökan/Vårdnadshavare/*">
    <person>
    ...

Your next mistake is that you use:

<xsl:value-of select="personnummer"/>

instead of:

 <xsl:value-of select="@personnummer"/>

Finally, Förnamn and Efternamn are direct children of Vårdnadshavare1 / Vårdnadshavare2 - so an expression like Vårdnadshavare/Förnamn does not select anything.

Try this corrected stylesheet:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
  <xsl:template match="/">
    <begaraninkomstuppgift>
      <xsl:for-each select="Förskoleansökan/Vårdnadshavare/*">
        <person>
          <xsl:attribute name="personummer">
            <xsl:value-of select="@personnummer"/>
          </xsl:attribute>
          <fornamn>
            <xsl:value-of select="Förnamn" />
          </fornamn>
          <efternamn>
            <xsl:value-of select="Efternamn" />
          </efternamn>
        </person>
      </xsl:for-each>
    </begaraninkomstuppgift>
  </xsl:template>
</xsl:stylesheet>

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