Получение / документирование дочерних узлов контекста с XPath - PullRequest
3 голосов
/ 09 февраля 2011

В другом потоке об использовании XSLT для перечисления каждого узла в файле XML, Алехандро предложил этот полезный фрагмент кода XPath 2.0:

РЕДАКТИРОВАТЬ: моя таблица стилейниже теперь используется модифицированная версия кода, которую Алехандро любезно разместил в комментарии.Он сообщает атрибут @name элементов.

Я сильно изменил его, чтобы применить к схеме .xsd, например:

Пример схемы

(упрощенная версия этого источника )

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:annotation>
    <xsd:documentation xml:lang="en">
 Purchase order schema for Example.com.
 Copyright 2000 Example.com. All rights reserved.
</xsd:documentation>
</xsd:annotation>
<xsd:element name="comment" type="xsd:string">
    <xsd:annotation>
        <xsd:documentation>doc for comment</xsd:documentation>
    </xsd:annotation>
</xsd:element>
<xsd:complexType name="USAddress">
    <xsd:annotation>
        <xsd:documentation>doc for USAddress</xsd:documentation>
    </xsd:annotation>
    <xsd:sequence>
        <xsd:element name="name" type="xsd:string"/>
        <xsd:element name="street" type="xsd:string"/>
        <xsd:element name="city" type="xsd:string"/>
        <xsd:element name="state" type="xsd:string"/>
        <xsd:element name="zip" type="xsd:decimal"/>
    </xsd:sequence>
    <xsd:attribute name="country" type="xsd:NMTOKEN" fixed="US"/>
</xsd:complexType>
<!-- Stock Keeping Unit, a code for identifying products -->
<xsd:simpleType name="SKU">
    <xsd:annotation>
        <xsd:documentation>doc for SKU</xsd:documentation>
    </xsd:annotation>
    <xsd:restriction base="xsd:string">
        <xsd:pattern value="\d{3}-[A-Z]{2}"/>
    </xsd:restriction>
</xsd:simpleType>
</xsd:schema>
Моя таблица стилей XSLT:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsl:template match="*|@*">
<xsl:value-of select="
string-join(
distinct-values(
(//*|//@*)
/string-join(
(ancestor::node()/name(),
if (self::attribute())
    then concat('@',name())
    else if (self::*[@name]) 
        then concat(name(),'[@name=&quot;',@name,'&quot;]')
        else name()),
'/')),
'&#xA;')
"/>
    </xsl:template>
    </xsl:stylesheet>
Результаты:
/xsd:schema
/xsd:schema/xsd:annotation
/xsd:schema/xsd:annotation/xsd:documentation
/xsd:schema/xsd:annotation/xsd:documentation/@xml:lang
/xsd:schema/xsd:element[@name="comment"]
/xsd:schema/xsd:element/@name
/xsd:schema/xsd:element/@type
/xsd:schema/xsd:element/xsd:annotation
/xsd:schema/xsd:element/xsd:annotation/xsd:documentation
/xsd:schema/xsd:complexType[@name="USAddress"]
/xsd:schema/xsd:complexType/@name
/xsd:schema/xsd:complexType/xsd:annotation
/xsd:schema/xsd:complexType/xsd:annotation/xsd:documentation
/xsd:schema/xsd:complexType/xsd:sequence
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="name"]
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@name
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@type
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="street"]
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="city"]
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="state"]
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element[@name="zip"]
/xsd:schema/xsd:complexType/xsd:attribute[@name="country"]
/xsd:schema/xsd:complexType/xsd:attribute/@name
/xsd:schema/xsd:complexType/xsd:attribute/@type
/xsd:schema/xsd:complexType/xsd:attribute/@fixed
/xsd:schema/xsd:simpleType[@name="SKU"]
/xsd:schema/xsd:simpleType/@name
/xsd:schema/xsd:simpleType/xsd:annotation
/xsd:schema/xsd:simpleType/xsd:annotation/xsd:documentation
/xsd:schema/xsd:simpleType/xsd:restriction
/xsd:schema/xsd:simpleType/xsd:restriction/@base
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern/@value

Этот вывод подходит для целей этого вопроса.

Теперь вместо того, чтобы спрашивать "что не так"с моим бестолковым кодом?Я просто попрошу наилучший способ перейти из базового состояния, которое действительно работает.

Мне нужно добавить предложение, которое для каждой строки с внуком /xsd:documentation добавляет текст из <xsd:documentation>foo</xsd:documentation>.Итак, эта строка:

/xsd:schema/xsd:element[@name="comment"]

становится:

/xsd:schema/xsd:element[@name="comment"] | doc for comment

Спасибо, Мэтт

Ответы [ 2 ]

3 голосов
/ 09 февраля 2011

Решение простое :

.1.Определите пространство имен xsd в таблице стилей:

<xsl:stylesheet version="2.0"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
>

.2.Измените:

.//documentation

на

.//xsd:documentation

Кстати, это неправильно :

//xsd|//@*

Нет элемента с именем xsdв документе.Возможно, вы хотите:

//xsd:*|//@* 

Кроме того, нет необходимости использовать local-name() для атрибутов, просто name() в порядке.

Второе наблюдение:

В решении Алехандро нет ничего плохого.Применительно к предоставленному XML-документу он выдает следующий правильный вывод:

/xsd:schema
/xsd:schema/xsd:annotation
/xsd:schema/xsd:annotation/xsd:documentation
/xsd:schema/xsd:annotation/xsd:documentation/@xml:lang
/xsd:schema/xsd:element
/xsd:schema/xsd:element/@name
/xsd:schema/xsd:element/@type
/xsd:schema/xsd:element/xsd:annotation
/xsd:schema/xsd:element/xsd:annotation/xsd:documentation
/xsd:schema/xsd:complexType
/xsd:schema/xsd:complexType/@name
/xsd:schema/xsd:complexType/xsd:sequence
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@name
/xsd:schema/xsd:complexType/xsd:sequence/xsd:element/@type
/xsd:schema/xsd:complexType/xsd:attribute
/xsd:schema/xsd:complexType/xsd:attribute/@name
/xsd:schema/xsd:complexType/xsd:attribute/@type
/xsd:schema/xsd:complexType/xsd:attribute/@fixed
/xsd:schema/xsd:complexType/xsd:annotation
/xsd:schema/xsd:complexType/xsd:annotation/xsd:documentation
/xsd:schema/xsd:simpleType
/xsd:schema/xsd:simpleType/@name
/xsd:schema/xsd:simpleType/xsd:restriction
/xsd:schema/xsd:simpleType/xsd:restriction/@base
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern
/xsd:schema/xsd:simpleType/xsd:restriction/xsd:pattern/@value
/xsd:schema/xsd:simpleType/xsd:annotation
/xsd:schema/xsd:simpleType/xsd:annotation/xsd:documentation
0 голосов
/ 10 февраля 2011

.//xsd:documentation пытался получить всю дочернюю документацию в схеме.Я исправил проблему, используя ./xsd:documentation.

Новое предложение, которое сообщает документацию для любого элемента после теста, чтобы увидеть, является ли он атрибутом:

concat(
if (self::*[@name]) 
then @name
else name()
, ./xsd:documentation)

Спасибо всем за помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...