У меня проблемы с адаптацией XSLT для обработки некоторых дополнительных правил / логики атрибутов.
У меня есть «общие» и «специальные» XML-файлы, которые я объединяю с этим XSLT:
http://www2.informatik.hu -berlin.de / ~ obecker / XSLT / слияния / merge.xslt.html
Исходные файлы
general.xml
<?xml version="1.0" encoding="utf-8"?>
<settings>
<phone-settings e="2">
<language perm="RW">English</language>
<codec1_name idx="1" perm="">0</codec1_name>
<codec1_name idx="2" perm="">0</codec1_name>
</phone-settings>
</settings>
specific.xml
<?xml version="1.0" encoding="utf-8"?>
<settings>
<phone-settings e="2">
<language perm="RW">German</language>
<codec1_name idx="1" perm="R">8</codec1_name>
</phone-settings>
</settings>
- XML-документы объединены, конкретные заменяет общие.
- Если атрибуты и их значения точно совпадают, используются конкретные данные.
На данный момент преобразование работает хорошо, но я должен внести коррективы:
- Некоторые элементы имеют атрибут 'idx', который уникально идентифицирует этот элемент
- Некоторые элементы имеют атрибут 'perm', который определяет, будет ли пользователь читать / писать.
Если один и тот же элемент существует в обоих исходных файлах, но с другим атрибутом 'perm', XSLT считает его уникальным и вводится дублирующий элемент:
<?xml version="1.0" encoding="utf-8"?>
<settings>
<phone-settings e="2">
<language perm="RW">German</language>
<codec1_name idx="1" perm="">0</codec1_name>
<codec1_name idx="2" perm="">0</codec1_name>
<codec1_name idx="1" perm="R">8</codec1_name>
</phone-settings>
</settings>
Вот шаблон XSLT, который обрабатывает сравнение с одним узлом:
<xslt:template name="m:compare-nodes">
<xslt:param name="node1" />
<xslt:param name="node2" />
<xslt:variable name="type1">
<xslt:apply-templates mode="m:detect-type" select="$node1" />
</xslt:variable>
<xslt:variable name="type2">
<xslt:apply-templates mode="m:detect-type" select="$node2" />
</xslt:variable>
<xslt:choose>
<!-- Are $node1 and $node2 element nodes with the same name? -->
<xslt:when test="$type1='element' and $type2='element' and local-name($node1)=local-name($node2) and namespace-uri($node1)=namespace-uri($node2) and name($node1)!=$dontmerge and name($node2)!=$dontmerge">
<!-- Comparing the attributes -->
<xslt:variable name="diff-att">
<!-- same number ... -->
<xslt:if test="count($node1/@*)!=count($node2/@*)">.</xslt:if>
<!-- ... and same name/content -->
<xslt:for-each select="$node1/@*">
<xslt:if test="not($node2/@* [local-name()=local-name(current()) and namespace-uri()=namespace-uri(current()) and .=current()])">.</xslt:if>
</xslt:for-each>
</xslt:variable>
<xslt:choose>
<xslt:when test="string-length($diff-att)!=0">!</xslt:when>
<xslt:otherwise>=</xslt:otherwise>
</xslt:choose>
</xslt:when>
<!-- Other nodes: test for the same type and content -->
<xslt:when test="$type1!='element' and $type1=$type2 and name($node1)=name($node2) and ($node1=$node2 or ($normalize='yes' and normalize-space($node1)= normalize-space($node2)))">=</xslt:when>
<!-- Otherwise: different node types or different name/content -->
<xslt:otherwise>!</xslt:otherwise>
</xslt:choose>
</xslt:template>
Я могу исключить атрибут 'perm' из соответствия следующим образом:
<!-- ... and same name/content -->
<xslt:for-each select="$node1/@* [name(.)!='perm']">
Это решает проблему дублирования элементов, к сожалению, это также означает, что значение этого атрибута в конкретном XML-файле - в данном случае 'R' не объединяется:
<?xml version="1.0" encoding="utf-8"?>
<settings>
<phone-settings e="2">
<language perm="RW">German</language>
<codec1_name idx="1" perm="">8</codec1_name>
<codec1_name idx="2" perm="">0</codec1_name>
</phone-settings>
</settings>
Как я могу исключить атрибут 'perm' из теста уникальности, в то же время гарантируя, что его значение в определенном XML-файле используется при слиянии?
Желаемый результат объединения двух файлов примеров вверху:
<?xml version="1.0" encoding="utf-8"?>
<settings>
<phone-settings e="2">
<language perm="RW">German</language>
<codec1_name idx="1" perm="R">8</codec1_name>
<codec1_name idx="2" perm="">0</codec1_name>
</phone-settings>
</settings>
Любая помощь с этим будет высоко ценится!
Спасибо.