2

I have an XML file, like this:

<area1>
    <settings>
        <setting name="to_include">value</setting>
    </settings>
</area1>
<area2>
    <settings>
        <setting name="where_to_include">?????</setting>
    </settings>
</area2>

I want to include the value of the setting node "to_include" as value of setting node "where_to_include". How could I do it, in a pure XML way? XInclude? XPointer? XPath? XLink? Other?

I hoped I could do something like this:

<area2>
    <settings>
        <setting name="where_to_include">
            <xi:include href="SAMEFILE" xpointer="xpointer(/areas/area1/settings/setting[@name='debug'])">
                <xi:fallback>FALLBACK VALUE</xi:fallback>
        </setting>
    </settings>
</area2>

But with XInclude I cannot refer to the document itself while parsing it.

Kamafeather
  • 8,663
  • 14
  • 69
  • 99
  • Obviously, you have not taken the time to familiarize yourself with those XML technologies. What you need depends on the language/environment you are using. For example, there are solutions for Python (e.g. lxml), Java, PHP; there is XQuery and XSLT. How about looking at an XSLT tutorial before asking here? – Mathias Müller Nov 13 '14 at 12:24
  • Unfortunately I don't have the time to familiarise with all the XML technologies, but I try to do it step by step, when new needs come out. I already have a solution at my language level (PHP) but I'm not allowed to perform changes on it. Cause of that I was wondering if there where a pure XML solution without altering the external environment. (i also added an XPointer example to my question) – Kamafeather Nov 13 '14 at 13:05
  • Apologies, I slightly misunderstood your question. Are you sure XPointer and XLink are supported by your PHP solution? – Mathias Müller Nov 13 '14 at 13:28
  • And yes, xincludes pointing to the same file are not possible. How about writing a tiny XSLT transformation to do this? – Mathias Müller Nov 13 '14 at 13:54
  • My PHP solution relies on _libxml_ and all the XML features are managed by that. So yes, all the parsing is performed correctly and it supports XPointer(s) (already used in the past). – Kamafeather Nov 14 '14 at 09:45
  • By the way can you be more specific on what code should I use? I don't have experience with XSLT and don't get exactly what you mean I should do. By the way I already told that I'm not allowed to change anything on the PHP side, regarding the XML parsing/managing. Do you suggestion requires changes just to XML? – Kamafeather Nov 14 '14 at 09:48
  • I think what you require is not possible without changing the application that manages the XML. If that's not possible, there's no point in explaining what you'd have to do. (Otherwise I'm glad to write an answer explaining how you'd do it with XSLT.) – Mathias Müller Nov 14 '14 at 09:52
  • What I wonder about is that I can do it (with XInclude) pointing to another document, but it is not possible to refer to anything in the same document. This incapability looks like something weird to me and I believe that there should be a way to do it (at least referring the already parsed nodes). – Kamafeather Nov 14 '14 at 10:12
  • If the _xpointer_ could be used as node value, without relying on a XInclude tag; or if the XInclude could have a way to refer to itself... – Kamafeather Nov 14 '14 at 10:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/64933/discussion-between-mathias-muller-and-kamafeather). – Mathias Müller Nov 14 '14 at 11:03

1 Answers1

0

I don't quite understand the question, but I think I have an idea what you mean. This may not be what you're after. You mention XPointer and XInclude, which seem like overkill to me.

Here's an XSLT (1.0) solution. The stylesheet takes an XML file like the one you give in the question and plugs value in for ?????. (Your XML is, by the way, missing a wrapper element, so it is technically malformed. But I think I understand what you mean. I'll silently add areas as a document element, and that's how the stylesheet that follows works. You may need to tweak it to fit the XML you're actually working with.)

Here is the stylesheet:

<?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="*">
    <xsl:variable name="n" select="name (.)"/>
    <xsl:element name="{$n}">
      <xsl:for-each select="@*">
        <xsl:copy-of select="."/>
      </xsl:for-each>
      <xsl:apply-templates select="node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="text()">
    <xsl:copy-of select="."/>
  </xsl:template>

  <xsl:template match="/">
    <xsl:element name="areas">
      <xsl:apply-templates select="areas"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="areas">
    <xsl:apply-templates select="area1"/>
    <xsl:apply-templates select="area2"/>
  </xsl:template>

  <xsl:template match="text()[parent::setting[ancestor::area2]]">
    <xsl:apply-templates select="preceding::area1/settings/setting/text()"/>
  </xsl:template>
</xsl:stylesheet>

The stylesheet essentially just copies its input XML document, except at one point: when dealing with the setting under area2, it doesn't copy the text but goes back to the area1 node and copies the text under its setting. You can confirm that this works using any XSLT processor, e.g., xsltproc (it sounds like you have some non-trivial XML functionality at your disposal, so this should be pretty straightforward). Just make some changes to value and run the stylesheet on the changed XML document.

  • Please stop posting bad XSLT answers (everything I said [here](http://stackoverflow.com/a/29583141/1987598) applies). As you can see in the comments section, this question was discussed in chat - and is about an approach similar to XInclude. The OP said they are not allowed to make any changes to the pipeline that processed the XML documents. – Mathias Müller Apr 11 '15 at 22:49