1

Given:

File with data:

<doc>
     <a>some text(<p>text here</p>) or blank</a>
     <b>same</b>
</doc>

File with default values:

<doc>
     <a><p>Dummy text</p></a>
     <b><p>Dummy text</p></b>
</doc>

I got this xslt to get the defaults from the second file:

$file = file path with default values

<a>
    <xsl:choose>
        <xsl:when test="//a!= ''">
            <xsl:copy-of select="//a/p" />
        </xsl:when>
        <xsl:otherwise>
              <xsl:copy-of select="document($file)//a/p" />
        </xsl:otherwise>
    </xsl:choose>
</a>

With this it works well and all, the only problem is that I would like to make an iteration through the xml nodes and make an automated process to improve scalability and save time entering every time the same condition fro each node. But I can't find a way to use the document() function with variables for the xpath, document($file)$nodexpath doesn't work.

I might be missing something, just started recently with xslt, if any of you could give me some advice I would appreciate It greatly.

Thanks in advance.

EDIT: The actual data resembles more an xml like this, it can have more deepth levels.

   <doc>
       <object>
          <group1> 
              <a>(<p>text here</p> or blank)</a>
              <b>(<p>text here</p> or blank)</b>
              <c>
                 <c1>(<p>text here</p> or blank)</c1>
                 <c2>(<p>text here</p> or blank)</c2>
              </c>
          </group1>
          <group2>
              <d>(<p>text here</p> or blank)</d>
          </group2>
       </object>
    </doc>

2 Answers 2

1

You could try matching any element that doesn't contain a child element or text and pull the default based off of the name.

There doesn't seem to be a reason to try to match xpaths based on your example. If your actual data is more complicated, update your question and I can update my answer.

Example:

XML Input (Added empty a and b to get default values.)

<doc>
    <a>some text(<p>text here</p>) or blank</a>
    <a/>
    <b>same</b>
    <b/>
</doc>

so_defaults.xml

<doc>
    <a><p>Dummy text for "a".</p></a>
    <b><p>Dummy text for "b".</p></b>
</doc>

XSLT 1.0

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

    <xsl:variable name="defaults" select="document('so_defaults.xml')"/>

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

    <xsl:template match="*[not(*) and not(text())]">
        <xsl:copy>
            <xsl:apply-templates select="$defaults/*/*[name()=name(current())]/*"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

Output

<doc>
   <a>some text(<p>text here</p>) or blank</a>
   <a>
      <p>Dummy text for "a".</p>
   </a>
   <b>same</b>
   <b>
      <p>Dummy text for "b".</p>
   </b>
</doc>
Sign up to request clarification or add additional context in comments.

1 Comment

Well i actually have a more complex structure with more deepth levels, I will edit my queestion to put a better example
0

I've finally resolved it, I'm posting my solution here, thanks Daniel for your answer, it helped me a lot:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/*">
        <doc xml:lang="es">
            <object>
                <xsl:apply-templates select="*"/>
            </object>
        </doc>
    </xsl:template> 

    <xsl:template match="*">
        <xsl:copy>
            <xsl:choose>
              <xsl:when test="current() != ''">
                <xsl:choose>
                    <xsl:when test="self::p">
                        <xsl:copy-of select="node()"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="*"/>
                    </xsl:otherwise>
                </xsl:choose>
              </xsl:when>
              <xsl:otherwise>
                <xsl:variable name="file" select="document('template.xml')"/>
                <xsl:copy-of select ="$file//*[name()=name(current())]/p"/>
              </xsl:otherwise>
            </xsl:choose>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.