Laden...

[gelöst] XSLT: Selektionsprobleme

Erstellt von UNeverNo vor 9 Jahren Letzter Beitrag vor 9 Jahren 1.477 Views
UNeverNo Themenstarter:in
153 Beiträge seit 2007
vor 9 Jahren
[gelöst] XSLT: Selektionsprobleme

Ich habe folgende XML-Datei:


<?xml version="1.0" encoding="utf-8"?>
<nachricht xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://mynamespace.de/123">
  <ebene1>
    <kopf>
        <code xmlns="">0001</code>
    </kopf>
    <liste>
      <ebene2>
        <ebene3.1>
          <kopf>
            <typ>
              <code xmlns="">0002</code>
            </typ>
          </kopf>
          <ebene4.1> <!--das möchte ich selektieren -->
            <typ>
              <code xmlns="">0702</code>
            </typ>
          </ebene4.1>
        </ebene3.1>
      </ebene2>
      <ebene2>
        <ebene3.2>
          <kopf>
            <typ>
              <code xmlns="">0707</code>
            </typ>
          </kopf>
          <ebene4.2>
          </ebene4.2>
        </ebene3.2>
      </ebene2>
    </liste>
  </ebene1>
</nachricht>

und folgende Transformation:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://mynamespace.de/123">
	<xsl:template match="/">
		<xsl:for-each select="nachricht/ebene1/liste/ebene2/ebene3.1/ebene4.1">
			<text></text>
		</xsl:for-each>
	</xsl:template>
</xsl:stylesheet>

Allerdings wird eben in for-each nichts selektiert.
Das Problem scheint mit dem namespace zusammen zu hängen, da wenn ich das xmlns="http://mynamespace.de/123" aus der XML-Datei entferne die Selektion funktioniert.

Allerdings sollte es auch irgendwie anders gehen - nur wie?

Grüße,
Chris

"Wenn Architekten genauso bauen würden, wie Programmierer programmieren, dann würde der erste Specht, der vorbeikommt, die Zivilisation zerstören." (Steven Weinberg)

16.842 Beiträge seit 2008
vor 9 Jahren
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://mynamespace.de/123">
    <xsl:template match="/nachricht">
        <xsl:for-each select="nachricht/ebene1/liste/ebene2/ebene3.1/ebene4.1">
            <text></text>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

oder

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://mynamespace.de/123">
    <xsl:template match="/nachricht">
        <xsl:for-each select="/ebene1/liste/ebene2/ebene3.1/ebene4.1">
            <text></text>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Ansonsten: was erhoffst Du Dir durch xmlns="http://mynamespace.de/123" ?

I.d.R. ist es besser eigene Namespaces zu nutzen, wenn es die Aufgabe erfordert.

UNeverNo Themenstarter:in
153 Beiträge seit 2007
vor 9 Jahren

Hi, der Namespace ist vorgegeben. Ich habe das Problem nur etwas verkürzt/vereinfacht.

Deine beiden Vorschläge scheinen nicht zu funktionieren. Sowohl das hier (http://www.freeformatter.com/xsl-transformer.html) als auch Saxon wirft (wenig aussagekräftige) Fehler.

Meine Beispiel-Xsl funktioniert ja auch (wenn der Namespace entfernt werden würde).

Grüße,
Chris

"Wenn Architekten genauso bauen würden, wie Programmierer programmieren, dann würde der erste Specht, der vorbeikommt, die Zivilisation zerstören." (Steven Weinberg)

16.842 Beiträge seit 2008
vor 9 Jahren

http://www.freeformatter.com/xsl-transformer.html scheint nicht richtig zu funktionieren.
Ich habs per Visual Studio getestet und klappt einwandfrei.

UNeverNo Themenstarter:in
153 Beiträge seit 2007
vor 9 Jahren

Mhh aber Saxon funktioniert bei mir auch nicht. Wie genau hast Du es denn in Visual Studio transformiert? Kann es sein, dass Visual Studio da nicht so genau ist bei Namespaces?

Ich habe es jetzt noch auf W3School versucht (http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog), da bekomme ich auch ein Ergebnis, allerdings ziemlichen Quatsch, nämlich 0001 0002 0702 0707, erwarten würde ich <text></text> oder <text/>, was kam denn bei Dir im Visual Studio?

Und war es nicht so, dass Visual Studio nur XSLT 1.0 unterstützt?

Grüße,
Chris

"Wenn Architekten genauso bauen würden, wie Programmierer programmieren, dann würde der erste Specht, der vorbeikommt, die Zivilisation zerstören." (Steven Weinberg)

16.842 Beiträge seit 2008
vor 9 Jahren

Dein Problem ist im Grunde der default namespace.
Ich weiß nicht, was Du mit dem Setzen von "xmlns" erreichen willst. Normalerweise macht man eigene Namespaces mit "xmlns:myCustomNs".
"Korrekt" ist es eben, wenn xmlns auf http://www.w3.org/1999/XSL/Transform verweist.

Der Parser bzw. XPATH hat jetzt damit seine Probleme und es kann sein, dass es beim einen funktioniert und beim anderen nicht.
Ja, das widerspricht dem Standard. That's life.

Da Du nicht sagst, was Du mit dem Setzen des NS erreichen willst, kann ich Dir auch keinen vernünftigen Endvorschlag machen.

656 Beiträge seit 2008
vor 9 Jahren

Morgen!
Der "Name" vom Root-Knoten ist nicht "nachricht", sondern "{http://mynamespace.de/123}nachricht" (der Namespace - bzw. spezifischer die URI gehört da mit dazu).

Dein X-Path "/nachricht" matcht aber nur auf "nachricht" - drum kommt nix raus.
Zumindest mit X-Path 1.0. In X-Path 2.0 gibts die sogenannten Context-Namespaces, mit denen man sowas machen könnte; aber dafür braucht man halt auch die entsprechenden Libraries.

Wenn dir der Namespace bekannt ist, vergib einfach ein Prefix im XSLT, und benutz das:

<xsl:template match="/myns:nachricht" xmlns:myns="http://mynamespace.de/123">
  <xsl:for-each select="myns:ebene1/myns:liste/myns:ebene2/myns:ebene3.1/myns:ebene4.1">
    [...]
UNeverNo Themenstarter:in
153 Beiträge seit 2007
vor 9 Jahren

Da Du nicht sagst, was Du mit dem Setzen des NS erreichen willst, kann ich Dir auch keinen vernünftigen Endvorschlag machen.

Naja wie gesagt, die XML bekomme ich so, ich hab mir da gar nichts bei gedacht 😉

Morgen!
Der "Name" vom Root-Knoten ist nicht "nachricht", sondern "{[ &gt; ](http://mynamespace.de/123)}nachricht" (der Namespace - bzw. spezifischer die URI gehört da mit dazu).

Dein X-Path "/nachricht" matcht aber nur auf "nachricht" - drum kommt nix raus.
Zumindest mit X-Path 1.0. In X-Path 2.0 gibts die sogenannten Context-Namespaces, mit denen man sowas machen könnte; aber dafür braucht man halt auch die entsprechenden Libraries.

Wenn dir der Namespace bekannt ist, vergib einfach ein Prefix im XSLT, und benutz das:

<xsl:template match="/myns:nachricht" xmlns:myns="http://mynamespace.de/123">  
  <xsl:for-each select="myns:ebene1/myns:liste/myns:ebene2/myns:ebene3.1/myns:ebene4.1">  
    [...]  

Dank Dir das funktioniert 👍
Ich verwende wie gesagt Saxon, das unterstützt X-Path 2.0.

Grüße,
Chris

"Wenn Architekten genauso bauen würden, wie Programmierer programmieren, dann würde der erste Specht, der vorbeikommt, die Zivilisation zerstören." (Steven Weinberg)