#node.js #saxon-js
Вопрос:
Если у меня есть простой xsd-файл и простой xml-файл, может ли SaxonJS показать, какие элементы и какие атрибуты в xml не определены в xsd?
Я искал примеры, но пока ничего не смог найти.
Обновить
Я также приму ответ с кодом js (узел), который использует saxon-js для обхода xml-ресурса и проверяет элементы и атрибуты (не нужно проверять значения атрибутов) в xsd-ресурсе.
В какой-то степени эффективным способом.
Комментарии:
1. (На основе схемы) проверка не является особенностью Saxon-JS, насколько мне известно. Проверка на основе схемы-это то, что предоставляет Saxon EE для Java, .NET или C/C , но не Saxon-JS.
2. Можете ли вы показать небольшую, но репрезентативную схему и образец экземпляра? «Простой файл xsd» легко сказать, но, на мой взгляд, большинство схем не являются «простыми», мощность и гибкость вложенности и объединения различных вариантов типов, частиц затрудняют создание чего-то простого и простого в XSLT. Я думаю, что у Saxonica есть собственный валидатор схем, реализованный в XSLT, но я понятия не имею, захотят ли они его коммерциализировать и сможет ли Saxon-JS справиться с этим. Возможно, имеет смысл связаться с ними напрямую по адресу saxonica.plan.io/projects/saxon-js если здесь никто не появится.
3. Кроме того, «какие элементы и атрибуты в XML не определены» является расплывчатым, оно может быть легко использовать ключ в схеме найти
foo
объявление элемента дляfoo
экземпляра образца, но это не говорит что ли конкретное объявление находится в правильном месте для экземпляра элемента, чтобы быть действительным.4. @MartinHonnen Вы хотите сказать, что saxon-js не загружает ресурс xsd как xsd? Но так же, как xml? Я предположил, что после загрузки xsd вы можете искать элементы в какой-то древовидной структуре
5. Я не уверен, где вы ожидаете или видите обработку XSD в реализации XPath 3.1 и XSLT 3.0, такой как Saxon-JS, если только она не поддерживает XSLT и XPath с учетом схемы, чего, насколько я знаю, не делает Saxon-JS. Таким образом, анализ/обработка XSD как любого XML-документа с помощью XSLT/XPath представляется возможной, но, конечно, не в качестве комплексного инструмента для замены средства проверки схемы или объектной модели схемы.
Ответ №1:
Чтобы просто проверить наличие xs:element
элемента в схеме, достаточно ключа, то же самое для xs:attribute
. Но все это зависит от использования простых xs:element name="foo"
и xs:attribute name="att1"
деклараций и никоим образом не проверяет вложенность или структуру:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="element-by-name" match="xs:element" use="QName(/*/@targetNamespace, @name)"/>
<xsl:key name="attribute-by-name" match="xs:attribute" use="QName(/*/@targetNamespace, @name)"/>
<xsl:template match="*[not(key('element-by-name', node-name(), $schema-doc))]">
<element-not-declared>
<name>{node-name()}</name>
<path>{path()}</path>
</element-not-declared>
<xsl:next-match/>
</xsl:template>
<xsl:template match="@*[not(key('attribute-by-name', node-name(), $schema-doc))]">
<attribute-not-declared>
<name>{node-name()}</name>
<path>{path()}</path>
</attribute-not-declared>
</xsl:template>
<xsl:mode on-no-match="shallow-skip"/>
<xsl:template match="/" name="xsl:initial-template">
<xsl:next-match/>
<xsl:comment xmlns:saxon="http://saxon.sf.net/">Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
</xsl:template>
<xsl:param name="schema-doc">
<xs:schema>
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="items">
<xs:complexType>
<xs:sequence>
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:element name="foo" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</xsl:param>
</xsl:stylesheet>
Ввод образца
<?xml version="1.0" encoding="utf-8"?>
<root>
<items count="1">
<item>
<foo>foo 1</foo>
<bar>bar 1</bar>
</item>
</items>
</root>
при запуске с Saxon-JS 2.3 в браузере выдает
<attribute-not-declared>
<name>count</name>
<path>/Q{}root[1]/Q{}items[1]/@count</path>
</attribute-not-declared>
<element-not-declared>
<name>bar</name>
<path>/Q{}root[1]/Q{}items[1]/Q{}item[1]/Q{}bar[1]</path>
</element-not-declared>
<!--Run with Saxon-JS 2.3 Browser-->
но я проверил, что это работает с «Saxon-JS 2.3 Node.js» также.
Таким образом, это находит некоторые элементы или атрибуты, для которых не найдено соответствующего объявления, на основе ключей, используемых в схеме. Это просто поверхностный подход, даже без учета сложностей пространств имен и формы элементов или формы атрибутов и пространств имен.
Чтобы запустить код XSLT 3 с помощью SaxonJS, вы можете либо запустить XSLT, SaxonJS.XPath.evaluate
вызвав функцию XPath 3.1 transform
, как показано ниже, либо сначала использовать xslt3
инструмент командной строки для экспорта XSLT в SEF/JSON, который затем можно запустить с помощью SaxonJS.transform
.
const SaxonJS = require("saxon-js");
const xml = `<?xml version="1.0" encoding="utf-8"?>
<root>
<items count="1">
<item>
<foo>foo 1</foo>
<bar>bar 1</bar>
</item>
</items>
</root>`;
const xsd = `<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
expand-text="yes">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="element-by-name" match="xs:element" use="QName(/*/@targetNamespace, @name)"/>
<xsl:key name="attribute-by-name" match="xs:attribute" use="QName(/*/@targetNamespace, @name)"/>
<xsl:template match="*[not(key('element-by-name', node-name(), $schema-doc))]">
<element-not-declared>
<name>{node-name()}</name>
<path>{path()}</path>
</element-not-declared>
<xsl:next-match/>
</xsl:template>
<xsl:template match="@*[not(key('attribute-by-name', node-name(), $schema-doc))]">
<attribute-not-declared>
<name>{node-name()}</name>
<path>{path()}</path>
</attribute-not-declared>
</xsl:template>
<xsl:mode on-no-match="shallow-skip"/>
<xsl:template match="/" name="xsl:initial-template">
<xsl:next-match/>
<xsl:comment xmlns:saxon="http://saxon.sf.net/">Run with {system-property('xsl:product-name')} {system-property('xsl:product-version')} {system-property('Q{http://saxon.sf.net/}platform')}</xsl:comment>
</xsl:template>
<xsl:param name="schema-doc">
<xs:schema>
<xs:element name="root">
<xs:complexType>
<xs:sequence>
<xs:element name="items">
<xs:complexType>
<xs:sequence>
<xs:element name="item" maxOccurs="unbounded">
<xs:complexType>
<xs:element name="foo" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
</xsl:param>
</xsl:stylesheet>`;
const result = SaxonJS.XPath.evaluate(`
transform(
map {
'source-node' : parse-xml($xml),
'stylesheet-text' : $xsd,
'delivery-format' : 'serialized'
}
)?output`,
[],
{
params : { xml : xml, xsd : xsd }
}
);
console.log(result);
Выход
<?xml version="1.0" encoding="UTF-8"?>
<attribute-not-declared>
<name>count</name>
<path>/Q{}root[1]/Q{}items[1]/@count</path>
</attribute-not-declared>
<element-not-declared>
<name>bar</name>
<path>/Q{}root[1]/Q{}items[1]/Q{}item[1]/Q{}bar[1]</path>
</element-not-declared>
<!--Run with Saxon-JS 2.3 Node.js-->
Комментарии:
1. Честно говоря: я как бы ищу «код js (узел)»
2. Я еще не поблагодарил вас за ваш (подробный) ответ. Спасибо! Это очень полезно. К сожалению, когда я увидел, что вы добавили код js, я больше не мог присуждать награду.